From c1f3adc4a4cd53e0b44b7f4bbb11a676d9c16f91 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 9 May 2006 20:24:19 +0200 Subject: [PATCH] user: Use handles for 32-bit window procedures instead of pointers into the bss segment. --- dlls/user/winproc.c | 233 ++++++++++++++++---------------------------- 1 file changed, 82 insertions(+), 151 deletions(-) diff --git a/dlls/user/winproc.c b/dlls/user/winproc.c index e885784b941..31a5632530e 100644 --- a/dlls/user/winproc.c +++ b/dlls/user/winproc.c @@ -59,25 +59,7 @@ typedef struct BYTE ljmp; /* ljmp relay*/ DWORD relay_offset; /* __wine_call_wndproc_32A/W */ WORD relay_sel; -} WINPROC_THUNK_FROM16; - -/* Window procedure 32-to-16-bit thunk */ -typedef struct -{ - BYTE popl_eax; /* popl %eax (return address) */ - BYTE pushl_func; /* pushl $proc */ - WNDPROC16 proc; - BYTE pushl_eax; /* pushl %eax */ - BYTE jmp; /* jmp relay (relative jump)*/ - void (*relay)(); /* WINPROC_CallProc32ATo16() */ -} WINPROC_THUNK_FROM32; - -/* Simple jmp to call 32-bit procedure directly */ -typedef struct -{ - BYTE jmp; /* jmp proc (relative jump) */ - WNDPROC proc; -} WINPROC_JUMP; +} WINPROC_THUNK; #include "poppack.h" @@ -86,40 +68,18 @@ typedef struct typedef struct { WNDPROC proc; -} WINPROC_THUNK_FROM16; - -typedef struct -{ - WNDPROC16 proc; -} WINPROC_THUNK_FROM32; - -typedef struct -{ - WNDPROC proc; -} WINPROC_JUMP; +} WINPROC_THUNK; #endif /* __i386__ */ -typedef union -{ - WINPROC_THUNK_FROM16 t_from16; - WINPROC_THUNK_FROM32 t_from32; -} WINPROC_THUNK; - typedef struct tagWINDOWPROC { WINPROC_THUNK thunk; /* Thunk */ - WINPROC_JUMP jmp; /* Jump */ BYTE type; /* Function type */ + WNDPROC16 proc16; /* 16-bit window proc */ } WINDOWPROC; -static LRESULT WINAPI WINPROC_CallProc32ATo16( WNDPROC16 func, HWND hwnd, - UINT msg, WPARAM wParam, - LPARAM lParam ); -static LRESULT WINAPI WINPROC_CallProc32WTo16( WNDPROC16 func, HWND hwnd, - UINT msg, WPARAM wParam, - LPARAM lParam ); - +#define WINPROC_HANDLE (~0UL >> 16) #define MAX_WINPROCS (0x10000 / sizeof(WINDOWPROC)) static WINDOWPROC winproc_array[MAX_WINPROCS]; @@ -151,7 +111,7 @@ static inline WINDOWPROC *find_winproc16( WNDPROC16 func ) for (i = 0; i < winproc_used; i++) { - if (winproc_array[i].type == WIN_PROC_16 && winproc_array[i].thunk.t_from32.proc == func) + if (winproc_array[i].type == WIN_PROC_16 && winproc_array[i].proc16 == func) return &winproc_array[i]; } return NULL; @@ -165,7 +125,7 @@ static inline WINDOWPROC *find_winproc( WNDPROC func, WINDOWPROCTYPE type ) for (i = 0; i < winproc_used; i++) { - if (winproc_array[i].type == type && winproc_array[i].thunk.t_from16.proc == func) + if (winproc_array[i].type == type && winproc_array[i].thunk.proc == func) return &winproc_array[i]; } return NULL; @@ -174,18 +134,7 @@ static inline WINDOWPROC *find_winproc( WNDPROC func, WINDOWPROCTYPE type ) /* initialize a new 16-bit winproc */ static inline void set_winproc16( WINDOWPROC *proc, WNDPROC16 func ) { -#ifdef __i386__ - proc->thunk.t_from32.popl_eax = 0x58; /* popl %eax */ - proc->thunk.t_from32.pushl_func = 0x68; /* pushl $proc */ - proc->thunk.t_from32.proc = func; - proc->thunk.t_from32.pushl_eax = 0x50; /* pushl %eax */ - proc->thunk.t_from32.jmp = 0xe9; /* jmp relay*/ - proc->thunk.t_from32.relay = /* relative jump */ - (void(*)())((DWORD)WINPROC_CallProc32ATo16 - - (DWORD)(&proc->thunk.t_from32.relay + 1)); -#else /* __i386__ */ - proc->thunk.t_from32.proc = func; -#endif /* __i386__ */ + proc->proc16 = func; proc->type = WIN_PROC_16; } @@ -195,36 +144,32 @@ static inline void set_winproc( WINDOWPROC *proc, WNDPROC func, WINDOWPROCTYPE t #ifdef __i386__ static FARPROC16 relay_32A, relay_32W; - proc->thunk.t_from16.popl_eax = 0x58; /* popl %eax */ - proc->thunk.t_from16.pushl_func = 0x68; /* pushl $proc */ - proc->thunk.t_from16.proc = func; - proc->thunk.t_from16.pushl_eax = 0x50; /* pushl %eax */ - proc->thunk.t_from16.ljmp = 0xea; /* ljmp relay*/ + proc->thunk.popl_eax = 0x58; /* popl %eax */ + proc->thunk.pushl_func = 0x68; /* pushl $proc */ + proc->thunk.pushl_eax = 0x50; /* pushl %eax */ + proc->thunk.ljmp = 0xea; /* ljmp relay*/ switch(type) { case WIN_PROC_32A: if (!relay_32A) relay_32A = GetProcAddress16( GetModuleHandle16("user"), "__wine_call_wndproc_32A" ); - proc->thunk.t_from16.relay_offset = OFFSETOF(relay_32A); - proc->thunk.t_from16.relay_sel = SELECTOROF(relay_32A); + proc->thunk.relay_offset = OFFSETOF(relay_32A); + proc->thunk.relay_sel = SELECTOROF(relay_32A); break; case WIN_PROC_32W: if (!relay_32W) relay_32W = GetProcAddress16( GetModuleHandle16("user"), "__wine_call_wndproc_32W" ); - proc->thunk.t_from16.relay_offset = OFFSETOF(relay_32W); - proc->thunk.t_from16.relay_sel = SELECTOROF(relay_32W); + proc->thunk.relay_offset = OFFSETOF(relay_32W); + proc->thunk.relay_sel = SELECTOROF(relay_32W); break; default: /* Should not happen */ assert(0); break; } - proc->jmp.jmp = 0xe9; - /* Fixup relative jump */ - proc->jmp.proc = (WNDPROC)((DWORD)func - (DWORD)(&proc->jmp.proc + 1)); -#else /* __i386__ */ - proc->thunk.t_from16.proc = func; #endif /* __i386__ */ + proc->thunk.proc = func; + proc->proc16 = 0; proc->type = type; } @@ -247,6 +192,35 @@ static WORD get_winproc_selector(void) return ret; } +/* 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]; +} + +/* 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) == get_winproc_selector()) + { + BYTE *ptr = (BYTE *)winproc_array + LOWORD(handle); + /* It must be the thunk address */ + WINDOWPROC *proc = (WINDOWPROC *)(ptr - FIELD_OFFSET(WINDOWPROC,thunk)); + if (is_valid_winproc(proc)) return proc; + return NULL; + } + return handle_to_proc( (WNDPROC)handle ); +} + +/* 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)); +} + #ifdef __i386__ /* Some window procedures modify register they shouldn't, or are not @@ -481,43 +455,6 @@ static LRESULT WINAPI WINPROC_CallWndProc16( WNDPROC16 proc, HWND16 hwnd, } -/********************************************************************** - * WINPROC_GetPtr - * - * Return a pointer to the win proc. - */ -static WINDOWPROC *WINPROC_GetPtr( WNDPROC handle ) -{ - BYTE *ptr; - WINDOWPROC *proc; - - /* ptr cannot be < 64K */ - if (!HIWORD(handle)) return NULL; - - /* Check for a linear pointer */ - - ptr = (BYTE *)handle; - /* First check if it is the jmp address */ - proc = (WINDOWPROC *)(ptr - FIELD_OFFSET(WINDOWPROC,jmp)); - if (is_valid_winproc(proc)) return proc; - - /* Now it must be the thunk address */ - proc = (WINDOWPROC *)(ptr - FIELD_OFFSET(WINDOWPROC,thunk)); - if (is_valid_winproc(proc)) return proc; - - /* Check for a segmented pointer */ - - if (HIWORD(handle) == get_winproc_selector()) - { - ptr = (BYTE *)winproc_array + LOWORD(handle); - /* It must be the thunk address */ - proc = (WINDOWPROC *)(ptr - FIELD_OFFSET(WINDOWPROC,thunk)); - if (is_valid_winproc(proc)) return proc; - } - return NULL; -} - - /********************************************************************** * WINPROC_GetProc16 * @@ -525,12 +462,12 @@ static WINDOWPROC *WINPROC_GetPtr( WNDPROC handle ) */ WNDPROC16 WINPROC_GetProc16( WNDPROC proc ) { - WINDOWPROC *ptr = (WINDOWPROC *)proc; + WINDOWPROC *ptr = handle_to_proc( proc ); - if (!proc) return 0; + if (!ptr) return 0; if (ptr->type == WIN_PROC_16) - return ptr->thunk.t_from32.proc; + return ptr->proc16; else return (WNDPROC16)MAKESEGPTR( get_winproc_selector(), (char *)&ptr->thunk - (char *)winproc_array ); @@ -544,18 +481,10 @@ WNDPROC16 WINPROC_GetProc16( WNDPROC proc ) */ WNDPROC WINPROC_GetProc( WNDPROC proc, WINDOWPROCTYPE type ) { - WINDOWPROC *ptr = (WINDOWPROC *)proc; + WINDOWPROC *ptr = handle_to_proc( proc ); - if (!proc) return NULL; - - if (ptr->type == WIN_PROC_16) - return (WNDPROC)&ptr->thunk; - else if (type != ptr->type) - /* Have to return the jmp address if types don't match */ - return (WNDPROC)&ptr->jmp; - else - /* Some Win16 programs want to get back the proc they set */ - return (WNDPROC)ptr->thunk.t_from16.proc; + if (!ptr || type != ptr->type) return proc; + return ptr->thunk.proc; /* we can return the original proc in that case */ } @@ -577,7 +506,7 @@ WNDPROC WINPROC_AllocProc16( WNDPROC16 func ) EnterCriticalSection( &winproc_cs ); /* check if the function is already a win proc */ - if (!(proc = WINPROC_GetPtr( (WNDPROC)func ))) + if (!(proc = handle16_to_proc( func ))) { /* then check if we already have a winproc for that function */ if (!(proc = find_winproc16( func ))) @@ -589,14 +518,14 @@ WNDPROC WINPROC_AllocProc16( WNDPROC16 func ) proc = &winproc_array[winproc_used++]; set_winproc16( proc, func ); TRACE( "allocated %p for %p/16-bit (%d/%d used)\n", - proc, func, winproc_used, MAX_WINPROCS ); + proc_to_handle(proc), func, winproc_used, MAX_WINPROCS ); } } - else TRACE( "reusing %p for %p/16-bit\n", proc, func ); + else TRACE( "reusing %p for %p/16-bit\n", proc_to_handle(proc), func ); } LeaveCriticalSection( &winproc_cs ); - return (WNDPROC)proc; + return proc_to_handle( proc ); } @@ -618,7 +547,7 @@ WNDPROC WINPROC_AllocProc( WNDPROC func, WINDOWPROCTYPE type ) EnterCriticalSection( &winproc_cs ); /* check if the function is already a win proc */ - if (!(proc = WINPROC_GetPtr( func ))) + if (!(proc = handle_to_proc( func ))) { /* then check if we already have a winproc for that function */ if (!(proc = find_winproc( func, type ))) @@ -630,14 +559,14 @@ WNDPROC WINPROC_AllocProc( WNDPROC func, WINDOWPROCTYPE type ) proc = &winproc_array[winproc_used++]; set_winproc( proc, func, type ); TRACE( "allocated %p for %p/%d (%d/%d used)\n", - proc, func, type, winproc_used, MAX_WINPROCS ); + proc_to_handle(proc), func, type, winproc_used, MAX_WINPROCS ); } } - else TRACE( "reusing %p for %p/%d\n", proc, func, type ); + else TRACE( "reusing %p for %p/%d\n", proc_to_handle(proc), func, type ); } LeaveCriticalSection( &winproc_cs ); - return (WNDPROC)proc; + return proc_to_handle( proc ); } @@ -648,9 +577,13 @@ WNDPROC WINPROC_AllocProc( WNDPROC func, WINDOWPROCTYPE type ) */ WINDOWPROCTYPE WINPROC_GetProcType( WNDPROC proc ) { - if (!proc) return WIN_PROC_INVALID; - return ((WINDOWPROC *)proc)->type; + WINDOWPROC *ptr = handle_to_proc( proc ); + + if (!ptr) return WIN_PROC_INVALID; + return ptr->type; } + + /********************************************************************** * WINPROC_TestCBForStr * @@ -3186,9 +3119,8 @@ LRESULT WINAPI __wine_call_wndproc_32W( HWND16 hwnd, UINT16 msg, WPARAM16 wPara * * Call a 16-bit window procedure, translating the 32-bit args. */ -static LRESULT WINAPI WINPROC_CallProc32ATo16( WNDPROC16 func, HWND hwnd, - UINT msg, WPARAM wParam, - LPARAM lParam ) +static LRESULT WINPROC_CallProc32ATo16( WNDPROC16 func, HWND hwnd, + UINT msg, WPARAM wParam, LPARAM lParam ) { UINT16 msg16; MSGPARAM16 mp16; @@ -3211,9 +3143,8 @@ static LRESULT WINAPI WINPROC_CallProc32ATo16( WNDPROC16 func, HWND hwnd, * * Call a 16-bit window procedure, translating the 32-bit args. */ -static LRESULT WINAPI WINPROC_CallProc32WTo16( WNDPROC16 func, HWND hwnd, - UINT msg, WPARAM wParam, - LPARAM lParam ) +static LRESULT WINPROC_CallProc32WTo16( WNDPROC16 func, HWND hwnd, + UINT msg, WPARAM wParam, LPARAM lParam ) { UINT16 msg16; MSGPARAM16 mp16; @@ -3242,17 +3173,17 @@ LRESULT WINAPI CallWindowProc16( WNDPROC16 func, HWND16 hwnd, UINT16 msg, if (!func) return 0; - if (!(proc = WINPROC_GetPtr( (WNDPROC)func ))) + if (!(proc = handle16_to_proc( func ))) return WINPROC_CallWndProc16( func, hwnd, msg, wParam, lParam ); switch(proc->type) { case WIN_PROC_16: - return WINPROC_CallWndProc16( proc->thunk.t_from32.proc, hwnd, msg, wParam, lParam ); + return WINPROC_CallWndProc16( proc->proc16, hwnd, msg, wParam, lParam ); case WIN_PROC_32A: - return __wine_call_wndproc_32A( hwnd, msg, wParam, lParam, proc->thunk.t_from16.proc ); + return __wine_call_wndproc_32A( hwnd, msg, wParam, lParam, proc->thunk.proc ); case WIN_PROC_32W: - return __wine_call_wndproc_32W( hwnd, msg, wParam, lParam, proc->thunk.t_from16.proc ); + return __wine_call_wndproc_32W( hwnd, msg, wParam, lParam, proc->thunk.proc ); default: WARN_(relay)("Invalid proc %p\n", proc ); return 0; @@ -3295,17 +3226,17 @@ LRESULT WINAPI CallWindowProcA( if (!func) return 0; - if (!(proc = WINPROC_GetPtr( func ))) + if (!(proc = handle_to_proc( func ))) return WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam ); switch(proc->type) { case WIN_PROC_16: - return WINPROC_CallProc32ATo16( proc->thunk.t_from32.proc, hwnd, msg, wParam, lParam ); + return WINPROC_CallProc32ATo16( proc->proc16, hwnd, msg, wParam, lParam ); case WIN_PROC_32A: - return WINPROC_CallWndProc( proc->thunk.t_from16.proc, hwnd, msg, wParam, lParam ); + return WINPROC_CallWndProc( proc->thunk.proc, hwnd, msg, wParam, lParam ); case WIN_PROC_32W: - return WINPROC_CallProc32ATo32W( proc->thunk.t_from16.proc, hwnd, msg, wParam, lParam ); + return WINPROC_CallProc32ATo32W( proc->thunk.proc, hwnd, msg, wParam, lParam ); default: WARN_(relay)("Invalid proc %p\n", proc ); return 0; @@ -3325,17 +3256,17 @@ LRESULT WINAPI CallWindowProcW( WNDPROC func, HWND hwnd, UINT msg, if (!func) return 0; - if (!(proc = WINPROC_GetPtr( func ))) + if (!(proc = handle_to_proc( func ))) return WINPROC_CallWndProc( func, hwnd, msg, wParam, lParam ); switch(proc->type) { case WIN_PROC_16: - return WINPROC_CallProc32WTo16( proc->thunk.t_from32.proc, hwnd, msg, wParam, lParam ); + return WINPROC_CallProc32WTo16( proc->proc16, hwnd, msg, wParam, lParam ); case WIN_PROC_32A: - return WINPROC_CallProc32WTo32A( proc->thunk.t_from16.proc, hwnd, msg, wParam, lParam ); + return WINPROC_CallProc32WTo32A( proc->thunk.proc, hwnd, msg, wParam, lParam ); case WIN_PROC_32W: - return WINPROC_CallWndProc( proc->thunk.t_from16.proc, hwnd, msg, wParam, lParam ); + return WINPROC_CallWndProc( proc->thunk.proc, hwnd, msg, wParam, lParam ); default: WARN_(relay)("Invalid proc %p\n", proc ); return 0;