blob: 19694ce5fcfe1111dbda35e4d5cc3cb9a89293f2 [file] [log] [blame]
/*
* Emulator thunks
*
* Copyright 1996 Alexandre Julliard
*/
#include "windows.h"
#include "callback.h"
#include "heap.h"
#include "hook.h"
#include "module.h"
#include "stddebug.h"
#include "debug.h"
typedef void (*RELAY)();
#pragma pack(1)
typedef struct tagTHUNK
{
BYTE popl_eax; /* 0x58 popl %eax (return address)*/
BYTE pushl_func; /* 0x68 pushl $proc */
FARPROC32 proc WINE_PACKED;
BYTE pushl_eax; /* 0x50 pushl %eax */
BYTE jmp; /* 0xe9 jmp relay (relative jump)*/
RELAY relay WINE_PACKED;
struct tagTHUNK *next WINE_PACKED;
} THUNK;
#pragma pack(4)
#define DECL_THUNK(name,proc,relay) \
THUNK name = { 0x58, 0x68, (FARPROC32)(proc), 0x50, 0xe9, \
(RELAY)((char *)(relay) - (char *)(&(name).next)), NULL }
static THUNK *firstThunk = NULL;
/***********************************************************************
* THUNK_Alloc
*/
static THUNK *THUNK_Alloc( FARPROC32 func, RELAY relay )
{
THUNK *thunk = HeapAlloc( SystemHeap, 0, sizeof(*thunk) );
if (thunk)
{
thunk->popl_eax = 0x58;
thunk->pushl_func = 0x68;
thunk->proc = func;
thunk->pushl_eax = 0x50;
thunk->jmp = 0xe9;
thunk->relay = (RELAY)((char *)relay - (char *)(&thunk->next));
thunk->next = firstThunk;
firstThunk = thunk;
}
return thunk;
}
/***********************************************************************
* THUNK_Find
*/
static THUNK *THUNK_Find( FARPROC32 func )
{
THUNK *thunk = firstThunk;
while (thunk && (thunk->proc != func)) thunk = thunk->next;
return thunk;
}
/***********************************************************************
* THUNK_Free
*/
void THUNK_Free( THUNK *thunk )
{
if (HEAP_IsInsideHeap( SystemHeap, 0, thunk ))
{
THUNK **prev = &firstThunk;
while (*prev && (*prev != thunk)) prev = &(*prev)->next;
if (*prev)
{
*prev = thunk->next;
HeapFree( SystemHeap, 0, thunk );
return;
}
}
fprintf( stderr, "THUNK_Free: invalid thunk addr %p\n", thunk );
}
/***********************************************************************
* THUNK_EnumObjects16 (GDI.71)
*/
INT16 THUNK_EnumObjects16( HDC16 hdc, INT16 nObjType,
GOBJENUMPROC16 func, LPARAM lParam )
{
DECL_THUNK( thunk, func, CallTo16_word_ll );
return EnumObjects( hdc, nObjType, (GOBJENUMPROC16)&thunk, lParam );
}
/*************************************************************************
* THUNK_EnumFonts16 (GDI.70)
*/
INT16 THUNK_EnumFonts16( HDC16 hdc, LPCSTR lpFaceName,
FONTENUMPROC16 func, LPARAM lParam )
{
DECL_THUNK( thunk, func, CallTo16_word_llwl );
return EnumFonts( hdc, lpFaceName, (FONTENUMPROC16)&thunk, lParam );
}
/******************************************************************
* THUNK_EnumMetaFile16 (GDI.175)
*/
BOOL16 THUNK_EnumMetaFile16( HDC16 hdc, HMETAFILE16 hmf,
MFENUMPROC16 func, LPARAM lParam )
{
DECL_THUNK( thunk, func, CallTo16_word_wllwl );
return EnumMetaFile( hdc, hmf, (MFENUMPROC16)&thunk, lParam );
}
/*************************************************************************
* THUNK_EnumFontFamilies16 (GDI.330)
*/
INT16 THUNK_EnumFontFamilies16( HDC16 hdc, LPCSTR lpszFamily,
FONTENUMPROC16 func, LPARAM lParam )
{
DECL_THUNK( thunk, func, CallTo16_word_llwl );
return EnumFontFamilies( hdc, lpszFamily, (FONTENUMPROC16)&thunk, lParam );
}
/**********************************************************************
* THUNK_LineDDA16 (GDI.100)
*/
void THUNK_LineDDA16( INT16 nXStart, INT16 nYStart, INT16 nXEnd, INT16 nYEnd,
LINEDDAPROC16 func, LPARAM lParam )
{
DECL_THUNK( thunk, func, CallTo16_word_wwl );
LineDDA16( nXStart, nYStart, nXEnd, nYEnd, (LINEDDAPROC16)&thunk, lParam );
}
/**********************************************************************
* THUNK_LineDDA32 (GDI32.248)
*/
BOOL32 THUNK_LineDDA32( INT32 nXStart, INT32 nYStart, INT32 nXEnd, INT32 nYEnd,
LINEDDAPROC32 func, LPARAM lParam )
{
DECL_THUNK( thunk, func, CallTo32_3 );
return LineDDA32( nXStart, nYStart, nXEnd, nYEnd,
(LINEDDAPROC32)&thunk, lParam );
}
/*******************************************************************
* THUNK_EnumWindows16 (USER.54)
*/
BOOL16 THUNK_EnumWindows16( WNDENUMPROC16 func, LPARAM lParam )
{
DECL_THUNK( thunk, func, CallTo16_word_wl );
return EnumWindows16( (WNDENUMPROC16)&thunk, lParam );
}
/*******************************************************************
* THUNK_EnumWindows32 (USER32.192)
*/
BOOL32 THUNK_EnumWindows32( WNDENUMPROC32 func, LPARAM lParam )
{
DECL_THUNK( thunk, func, CallTo32_2 );
return EnumWindows32( (WNDENUMPROC32)&thunk, lParam );
}
/**********************************************************************
* THUNK_EnumChildWindows16 (USER.55)
*/
BOOL16 THUNK_EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
LPARAM lParam )
{
DECL_THUNK( thunk, func, CallTo16_word_wl );
return EnumChildWindows16( parent, (WNDENUMPROC16)&thunk, lParam );
}
/**********************************************************************
* THUNK_EnumChildWindows32 (USER32.177)
*/
BOOL32 THUNK_EnumChildWindows32( HWND32 parent, WNDENUMPROC32 func,
LPARAM lParam )
{
DECL_THUNK( thunk, func, CallTo32_2 );
return EnumChildWindows32( parent, (WNDENUMPROC32)&thunk, lParam );
}
/**********************************************************************
* THUNK_EnumTaskWindows16 (USER.225)
*/
BOOL16 THUNK_EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
LPARAM lParam )
{
DECL_THUNK( thunk, func, CallTo16_word_wl );
return EnumTaskWindows16( hTask, (WNDENUMPROC16)&thunk, lParam );
}
/**********************************************************************
* THUNK_EnumThreadWindows (USER32.189)
*/
BOOL32 THUNK_EnumThreadWindows( DWORD id, WNDENUMPROC32 func, LPARAM lParam )
{
DECL_THUNK( thunk, func, CallTo32_2 );
return EnumThreadWindows( id, (WNDENUMPROC32)&thunk, lParam );
}
/***********************************************************************
* THUNK_EnumProps16 (USER.27)
*/
INT16 THUNK_EnumProps16( HWND16 hwnd, PROPENUMPROC16 func )
{
DECL_THUNK( thunk, func, CallTo16_word_wlw );
return EnumProps16( hwnd, (PROPENUMPROC16)&thunk );
}
/***********************************************************************
* THUNK_EnumProps32A (USER32.185)
*/
INT32 THUNK_EnumProps32A( HWND32 hwnd, PROPENUMPROC32A func )
{
DECL_THUNK( thunk, func, CallTo32_3 );
return EnumProps32A( hwnd, (PROPENUMPROC32A)&thunk );
}
/***********************************************************************
* THUNK_EnumProps32W (USER32.188)
*/
INT32 THUNK_EnumProps32W( HWND32 hwnd, PROPENUMPROC32W func )
{
DECL_THUNK( thunk, func, CallTo32_3 );
return EnumProps32W( hwnd, (PROPENUMPROC32W)&thunk );
}
/***********************************************************************
* THUNK_EnumPropsEx32A (USER32.186)
*/
INT32 THUNK_EnumPropsEx32A( HWND32 hwnd, PROPENUMPROCEX32A func, LPARAM lParam)
{
DECL_THUNK( thunk, func, CallTo32_4 );
return EnumPropsEx32A( hwnd, (PROPENUMPROCEX32A)&thunk, lParam );
}
/***********************************************************************
* THUNK_EnumPropsEx32W (USER32.187)
*/
INT32 THUNK_EnumPropsEx32W( HWND32 hwnd, PROPENUMPROCEX32W func, LPARAM lParam)
{
DECL_THUNK( thunk, func, CallTo32_4 );
return EnumPropsEx32W( hwnd, (PROPENUMPROCEX32W)&thunk, lParam );
}
/***********************************************************************
* THUNK_GrayString16 (USER.185)
*/
BOOL16 THUNK_GrayString16( HDC16 hdc, HBRUSH16 hbr, GRAYSTRINGPROC16 func,
LPARAM lParam, INT16 cch, INT16 x, INT16 y,
INT16 cx, INT16 cy )
{
DECL_THUNK( thunk, func, CallTo16_word_wlw );
if (!func)
return GrayString( hdc, hbr, NULL, lParam, cch, x, y, cx, cy );
else
return GrayString( hdc, hbr, (GRAYSTRINGPROC16)&thunk, lParam, cch,
x, y, cx, cy );
}
/***********************************************************************
* THUNK_SetWindowsHook16 (USER.121)
*/
FARPROC16 THUNK_SetWindowsHook16( INT16 id, HOOKPROC16 proc )
{
HINSTANCE16 hInst = FarGetOwner( HIWORD(proc) );
HTASK16 hTask = (id == WH_MSGFILTER) ? GetCurrentTask() : 0;
THUNK *thunk = THUNK_Alloc( (FARPROC16)proc, (RELAY)CallTo16_long_wwl );
if (!thunk) return 0;
return (FARPROC16)SetWindowsHookEx16( id, (HOOKPROC16)thunk, hInst, hTask);
}
/***********************************************************************
* THUNK_UnhookWindowsHook16 (USER.234)
*/
BOOL16 THUNK_UnhookWindowsHook16( INT16 id, HOOKPROC16 proc )
{
BOOL16 ret = FALSE;
THUNK *thunk = THUNK_Find( (FARPROC16)proc );
if (thunk) ret = UnhookWindowsHook16( id, (HOOKPROC16)thunk );
return ret;
}
/***********************************************************************
* THUNK_SetWindowsHookEx16 (USER.291)
*/
HHOOK THUNK_SetWindowsHookEx16( INT16 id, HOOKPROC16 proc, HINSTANCE16 hInst,
HTASK16 hTask )
{
THUNK *thunk = THUNK_Alloc( (FARPROC16)proc, (RELAY)CallTo16_long_wwl );
if (!thunk) return 0;
return SetWindowsHookEx16( id, (HOOKPROC16)thunk, hInst, hTask );
}
/***********************************************************************
* THUNK_UnhookWindowHookEx16 (USER.292)
*/
BOOL16 THUNK_UnhookWindowsHookEx16( HHOOK hhook )
{
THUNK *thunk = (THUNK *)HOOK_GetProc16( hhook );
BOOL16 ret = UnhookWindowsHookEx16( hhook );
if (thunk) THUNK_Free( thunk );
return ret;
}
static FARPROC16 defDCHookProc = NULL;
/***********************************************************************
* THUNK_SetDCHook (GDI.190)
*/
BOOL16 THUNK_SetDCHook( HDC16 hdc, FARPROC16 proc, DWORD dwHookData )
{
THUNK *thunk, *oldThunk;
if (!defDCHookProc) /* Get DCHook Win16 entry point */
defDCHookProc = MODULE_GetEntryPoint( GetModuleHandle("USER"), 362 );
if (proc != defDCHookProc)
{
thunk = THUNK_Alloc( proc, (RELAY)CallTo16_word_wwll );
if (!thunk) return FALSE;
}
else thunk = (THUNK *)DCHook;
/* Free the previous thunk */
GetDCHook( hdc, (FARPROC16 *)&oldThunk );
if (oldThunk && (oldThunk != (THUNK *)DCHook)) THUNK_Free( oldThunk );
return SetDCHook( hdc, (FARPROC16)thunk, dwHookData );
}
/***********************************************************************
* THUNK_GetDCHook (GDI.191)
*/
DWORD THUNK_GetDCHook( HDC16 hdc, FARPROC16 *phookProc )
{
THUNK *thunk = NULL;
DWORD ret = GetDCHook( hdc, (FARPROC16 *)&thunk );
if (thunk)
{
if (thunk == (THUNK *)DCHook)
{
if (!defDCHookProc) /* Get DCHook Win16 entry point */
defDCHookProc = MODULE_GetEntryPoint( GetModuleHandle("USER"),
362 );
*phookProc = defDCHookProc;
}
else *phookProc = thunk->proc;
}
return ret;
}
struct thunkstruct
{
char magic[4];
DWORD x1;
DWORD x2;
};
UINT32 ThunkConnect32( struct thunkstruct *ths, LPSTR thunkfun16,
LPSTR module16, LPSTR module32, HMODULE32 hmod32,
DWORD dllinitarg1 )
{
HINSTANCE16 hmm;
fprintf(stdnimp,"ThunkConnect32(<struct>,%s,%s,%s,%x,%lx)\n",
thunkfun16,module32,module16,hmod32,dllinitarg1
);
fprintf(stdnimp," magic = %c%c%c%c\n",
ths->magic[0],
ths->magic[1],
ths->magic[2],
ths->magic[3]
);
fprintf(stdnimp," x1 = %lx\n",ths->x1);
fprintf(stdnimp," x2 = %lx\n",ths->x2);
hmm=LoadModule(module16,NULL);
return TRUE;
}