user: Separate the 16 and 32-bit versions of WINPROC_AllocProc.
This commit is contained in:
parent
4c40190620
commit
41b5e687fd
|
@ -177,6 +177,19 @@ static WNDPROC CLASS_GetProc( CLASS *classPtr, WINDOWPROCTYPE type )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* CLASS_SetProc16
|
||||||
|
*
|
||||||
|
* Set the class winproc for a given proc type.
|
||||||
|
* Returns the previous window proc.
|
||||||
|
*/
|
||||||
|
static void CLASS_SetProc16( CLASS *classPtr, WNDPROC16 newproc )
|
||||||
|
{
|
||||||
|
classPtr->winprocA = WINPROC_AllocProc16( newproc );
|
||||||
|
classPtr->winprocW = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* CLASS_SetProc
|
* CLASS_SetProc
|
||||||
*
|
*
|
||||||
|
@ -953,7 +966,7 @@ LONG WINAPI SetClassLong16( HWND16 hwnd16, INT16 offset, LONG newval )
|
||||||
case GCLP_WNDPROC:
|
case GCLP_WNDPROC:
|
||||||
if (!(class = get_class_ptr( hwnd, TRUE ))) return 0;
|
if (!(class = get_class_ptr( hwnd, TRUE ))) return 0;
|
||||||
retval = (LONG)CLASS_GetProc16( class );
|
retval = (LONG)CLASS_GetProc16( class );
|
||||||
CLASS_SetProc( class, (WNDPROC)newval, WIN_PROC_16 );
|
CLASS_SetProc16( class, (WNDPROC16)newval );
|
||||||
release_class_ptr( class );
|
release_class_ptr( class );
|
||||||
return retval;
|
return retval;
|
||||||
case GCLP_MENUNAME:
|
case GCLP_MENUNAME:
|
||||||
|
|
|
@ -2213,7 +2213,7 @@ LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
|
||||||
|
|
||||||
if (is_winproc)
|
if (is_winproc)
|
||||||
{
|
{
|
||||||
WNDPROC new_proc = WINPROC_AllocProc( (WNDPROC)newval, WIN_PROC_16 );
|
WNDPROC new_proc = WINPROC_AllocProc16( (WNDPROC16)newval );
|
||||||
WNDPROC old_proc = (WNDPROC)SetWindowLongA( WIN_Handle32(hwnd), offset, (LONG_PTR)new_proc );
|
WNDPROC old_proc = (WNDPROC)SetWindowLongA( WIN_Handle32(hwnd), offset, (LONG_PTR)new_proc );
|
||||||
return (LONG)WINPROC_GetProc16( (WNDPROC)old_proc );
|
return (LONG)WINPROC_GetProc16( (WNDPROC)old_proc );
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "wine/port.h"
|
#include "wine/port.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
@ -142,99 +143,88 @@ static BOOL is_valid_winproc( WINDOWPROC *proc )
|
||||||
return (proc->type != WIN_PROC_INVALID);
|
return (proc->type != WIN_PROC_INVALID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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].type == WIN_PROC_16 && winproc_array[i].thunk.t_from32.proc == func)
|
||||||
|
return &winproc_array[i];
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* find an existing winproc for a given function and type */
|
/* find an existing winproc for a given function and type */
|
||||||
/* FIXME: probably should do something more clever than a linear search */
|
/* FIXME: probably should do something more clever than a linear search */
|
||||||
static inline WINDOWPROC *find_winproc( WNDPROC func, WINDOWPROCTYPE type )
|
static inline WINDOWPROC *find_winproc( WNDPROC func, WINDOWPROCTYPE type )
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
if (type == WIN_PROC_16)
|
|
||||||
{
|
|
||||||
for (i = 0; i < winproc_used; i++)
|
for (i = 0; i < winproc_used; i++)
|
||||||
{
|
{
|
||||||
if (winproc_array[i].type == type &&
|
if (winproc_array[i].type == type && winproc_array[i].thunk.t_from16.proc == func)
|
||||||
winproc_array[i].thunk.t_from32.proc == (WNDPROC16)func)
|
|
||||||
return &winproc_array[i];
|
return &winproc_array[i];
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (i = 0; i < winproc_used; i++)
|
|
||||||
{
|
|
||||||
if (winproc_array[i].type == type &&
|
|
||||||
winproc_array[i].thunk.t_from16.proc == func)
|
|
||||||
return &winproc_array[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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->type = WIN_PROC_16;
|
||||||
|
}
|
||||||
|
|
||||||
/* initialize a new winproc */
|
/* initialize a new winproc */
|
||||||
static inline void set_winproc( WINDOWPROC *proc, WNDPROC func, WINDOWPROCTYPE type )
|
static inline void set_winproc( WINDOWPROC *proc, WNDPROC func, WINDOWPROCTYPE type )
|
||||||
{
|
{
|
||||||
#ifdef __i386__
|
#ifdef __i386__
|
||||||
static FARPROC16 relay_32A, relay_32W;
|
static FARPROC16 relay_32A, relay_32W;
|
||||||
|
|
||||||
switch(type)
|
|
||||||
{
|
|
||||||
case WIN_PROC_16:
|
|
||||||
proc->thunk.t_from32.popl_eax = 0x58; /* popl %eax */
|
|
||||||
proc->thunk.t_from32.pushl_func = 0x68; /* pushl $proc */
|
|
||||||
proc->thunk.t_from32.proc = (WNDPROC16)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));
|
|
||||||
break;
|
|
||||||
case WIN_PROC_32A:
|
|
||||||
if (!relay_32A) relay_32A = GetProcAddress16( GetModuleHandle16("user"),
|
|
||||||
"__wine_call_wndproc_32A" );
|
|
||||||
proc->thunk.t_from16.popl_eax = 0x58; /* popl %eax */
|
proc->thunk.t_from16.popl_eax = 0x58; /* popl %eax */
|
||||||
proc->thunk.t_from16.pushl_func = 0x68; /* pushl $proc */
|
proc->thunk.t_from16.pushl_func = 0x68; /* pushl $proc */
|
||||||
proc->thunk.t_from16.proc = func;
|
proc->thunk.t_from16.proc = func;
|
||||||
proc->thunk.t_from16.pushl_eax = 0x50; /* pushl %eax */
|
proc->thunk.t_from16.pushl_eax = 0x50; /* pushl %eax */
|
||||||
proc->thunk.t_from16.ljmp = 0xea; /* ljmp relay*/
|
proc->thunk.t_from16.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_offset = OFFSETOF(relay_32A);
|
||||||
proc->thunk.t_from16.relay_sel = SELECTOROF(relay_32A);
|
proc->thunk.t_from16.relay_sel = SELECTOROF(relay_32A);
|
||||||
proc->jmp.jmp = 0xe9;
|
|
||||||
/* Fixup relative jump */
|
|
||||||
proc->jmp.proc = (WNDPROC)((DWORD)func - (DWORD)(&proc->jmp.proc + 1));
|
|
||||||
break;
|
break;
|
||||||
case WIN_PROC_32W:
|
case WIN_PROC_32W:
|
||||||
if (!relay_32W) relay_32W = GetProcAddress16( GetModuleHandle16("user"),
|
if (!relay_32W) relay_32W = GetProcAddress16( GetModuleHandle16("user"),
|
||||||
"__wine_call_wndproc_32W" );
|
"__wine_call_wndproc_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.t_from16.relay_offset = OFFSETOF(relay_32W);
|
proc->thunk.t_from16.relay_offset = OFFSETOF(relay_32W);
|
||||||
proc->thunk.t_from16.relay_sel = SELECTOROF(relay_32W);
|
proc->thunk.t_from16.relay_sel = SELECTOROF(relay_32W);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Should not happen */
|
||||||
|
assert(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
proc->jmp.jmp = 0xe9;
|
proc->jmp.jmp = 0xe9;
|
||||||
/* Fixup relative jump */
|
/* Fixup relative jump */
|
||||||
proc->jmp.proc = (WNDPROC)((char *)func - (char *)(&proc->jmp.proc + 1));
|
proc->jmp.proc = (WNDPROC)((DWORD)func - (DWORD)(&proc->jmp.proc + 1));
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* Should not happen */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#else /* __i386__ */
|
#else /* __i386__ */
|
||||||
switch(type)
|
|
||||||
{
|
|
||||||
case WIN_PROC_16:
|
|
||||||
proc->thunk.t_from32.proc = (WNDPROC16)func;
|
|
||||||
break;
|
|
||||||
case WIN_PROC_32A:
|
|
||||||
case WIN_PROC_32W:
|
|
||||||
proc->thunk.t_from16.proc = func;
|
proc->thunk.t_from16.proc = func;
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* Should not happen */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif /* __i386__ */
|
#endif /* __i386__ */
|
||||||
|
|
||||||
proc->type = type;
|
proc->type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -569,6 +559,47 @@ WNDPROC WINPROC_GetProc( WNDPROC proc, WINDOWPROCTYPE type )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
EnterCriticalSection( &winproc_cs );
|
||||||
|
|
||||||
|
/* check if the function is already a win proc */
|
||||||
|
if (!(proc = WINPROC_GetPtr( (WNDPROC)func )))
|
||||||
|
{
|
||||||
|
/* then check if we already have a winproc for that function */
|
||||||
|
if (!(proc = find_winproc16( func )))
|
||||||
|
{
|
||||||
|
if (winproc_used >= MAX_WINPROCS)
|
||||||
|
FIXME( "too many winprocs, cannot allocate one for 16-bit %p\n", func );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else TRACE( "reusing %p for %p/16-bit\n", proc, func );
|
||||||
|
}
|
||||||
|
|
||||||
|
LeaveCriticalSection( &winproc_cs );
|
||||||
|
return (WNDPROC)proc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* WINPROC_AllocProc
|
* WINPROC_AllocProc
|
||||||
*
|
*
|
||||||
|
|
|
@ -53,6 +53,7 @@ typedef struct
|
||||||
struct tagWINDOWPROC;
|
struct tagWINDOWPROC;
|
||||||
|
|
||||||
extern WNDPROC16 WINPROC_GetProc16( WNDPROC proc );
|
extern WNDPROC16 WINPROC_GetProc16( WNDPROC proc );
|
||||||
|
extern WNDPROC WINPROC_AllocProc16( WNDPROC16 func );
|
||||||
extern WNDPROC WINPROC_GetProc( WNDPROC proc, WINDOWPROCTYPE type );
|
extern WNDPROC WINPROC_GetProc( WNDPROC proc, WINDOWPROCTYPE type );
|
||||||
extern WNDPROC WINPROC_AllocProc( WNDPROC func, WINDOWPROCTYPE type );
|
extern WNDPROC WINPROC_AllocProc( WNDPROC func, WINDOWPROCTYPE type );
|
||||||
extern WINDOWPROCTYPE WINPROC_GetProcType( WNDPROC proc );
|
extern WINDOWPROCTYPE WINPROC_GetProcType( WNDPROC proc );
|
||||||
|
|
|
@ -72,7 +72,7 @@ INT16 WINAPI MessageBox16( HWND16 hwnd, LPCSTR text, LPCSTR title, UINT16 type )
|
||||||
*/
|
*/
|
||||||
UINT16 WINAPI SetTimer16( HWND16 hwnd, UINT16 id, UINT16 timeout, TIMERPROC16 proc )
|
UINT16 WINAPI SetTimer16( HWND16 hwnd, UINT16 id, UINT16 timeout, TIMERPROC16 proc )
|
||||||
{
|
{
|
||||||
TIMERPROC proc32 = (TIMERPROC)WINPROC_AllocProc( (WNDPROC)proc, WIN_PROC_16 );
|
TIMERPROC proc32 = (TIMERPROC)WINPROC_AllocProc16( (WNDPROC16)proc );
|
||||||
return SetTimer( WIN_Handle32(hwnd), id, timeout, proc32 );
|
return SetTimer( WIN_Handle32(hwnd), id, timeout, proc32 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ UINT16 WINAPI SetTimer16( HWND16 hwnd, UINT16 id, UINT16 timeout, TIMERPROC16 pr
|
||||||
*/
|
*/
|
||||||
UINT16 WINAPI SetSystemTimer16( HWND16 hwnd, UINT16 id, UINT16 timeout, TIMERPROC16 proc )
|
UINT16 WINAPI SetSystemTimer16( HWND16 hwnd, UINT16 id, UINT16 timeout, TIMERPROC16 proc )
|
||||||
{
|
{
|
||||||
TIMERPROC proc32 = (TIMERPROC)WINPROC_AllocProc( (WNDPROC)proc, WIN_PROC_16 );
|
TIMERPROC proc32 = (TIMERPROC)WINPROC_AllocProc16( (WNDPROC16)proc );
|
||||||
return SetSystemTimer( WIN_Handle32(hwnd), id, timeout, proc32 );
|
return SetSystemTimer( WIN_Handle32(hwnd), id, timeout, proc32 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1323,7 +1323,7 @@ ATOM WINAPI RegisterClassEx16( const WNDCLASSEX16 *wc )
|
||||||
|
|
||||||
wc32.cbSize = sizeof(wc32);
|
wc32.cbSize = sizeof(wc32);
|
||||||
wc32.style = wc->style;
|
wc32.style = wc->style;
|
||||||
wc32.lpfnWndProc = WINPROC_AllocProc( (WNDPROC)wc->lpfnWndProc, WIN_PROC_16 );
|
wc32.lpfnWndProc = WINPROC_AllocProc16( wc->lpfnWndProc );
|
||||||
wc32.cbClsExtra = wc->cbClsExtra;
|
wc32.cbClsExtra = wc->cbClsExtra;
|
||||||
wc32.cbWndExtra = wc->cbWndExtra;
|
wc32.cbWndExtra = wc->cbWndExtra;
|
||||||
wc32.hInstance = HINSTANCE_32(GetExePtr(wc->hInstance));
|
wc32.hInstance = HINSTANCE_32(GetExePtr(wc->hInstance));
|
||||||
|
|
Loading…
Reference in New Issue