327 lines
8.0 KiB
C
327 lines
8.0 KiB
C
/*
|
|
* Win32s Universal Thunk API
|
|
*
|
|
* Copyright 1999 Ulrich Weigand
|
|
*
|
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include "wine/winbase16.h"
|
|
#include "windef.h"
|
|
#include "winbase.h"
|
|
#include "winreg.h"
|
|
#include "winternl.h"
|
|
#include "wownt32.h"
|
|
#include "wine/debug.h"
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(thunk);
|
|
|
|
#include "pshpack1.h"
|
|
|
|
typedef struct
|
|
{
|
|
BYTE popl_eax;
|
|
BYTE pushl;
|
|
DWORD target;
|
|
BYTE pushl_eax;
|
|
BYTE ljmp;
|
|
DWORD utglue16;
|
|
|
|
} UT16THUNK;
|
|
|
|
typedef struct
|
|
{
|
|
BYTE popl_eax;
|
|
BYTE pushl;
|
|
DWORD target;
|
|
BYTE pushl_eax;
|
|
BYTE jmp;
|
|
DWORD utglue32;
|
|
|
|
} UT32THUNK;
|
|
|
|
#include "poppack.h"
|
|
|
|
typedef struct _UTINFO
|
|
{
|
|
struct _UTINFO *next;
|
|
HMODULE hModule;
|
|
HMODULE16 hModule16;
|
|
|
|
UT16THUNK ut16;
|
|
UT32THUNK ut32;
|
|
|
|
} UTINFO;
|
|
|
|
static UTINFO *UT_head; /* head of Universal Thunk list */
|
|
|
|
typedef DWORD (CALLBACK *UTGLUEPROC)( LPVOID lpBuff, DWORD dwUserDefined );
|
|
|
|
BOOL WINAPI UTRegister( HMODULE hModule, LPSTR lpsz16BITDLL,
|
|
LPSTR lpszInitName, LPSTR lpszProcName,
|
|
FARPROC *ppfn32Thunk, FARPROC pfnUT32CallBack,
|
|
LPVOID lpBuff );
|
|
|
|
VOID WINAPI UTUnRegister( HMODULE hModule );
|
|
|
|
|
|
/****************************************************************************
|
|
* UTGlue16 (KERNEL.666) (KERNEL Wine-specific export)
|
|
*/
|
|
DWORD WINAPI UTGlue16( LPVOID lpBuff, DWORD dwUserDefined, SEGPTR *translationList,
|
|
UTGLUEPROC target )
|
|
{
|
|
INT i;
|
|
|
|
/* Convert arguments to flat pointers */
|
|
|
|
if ( translationList )
|
|
for ( i = 0; translationList[i]; i++ )
|
|
{
|
|
LPVOID flatPtr = MapSL( translationList[i] );
|
|
*(LPVOID *)flatPtr = MapSL( *(SEGPTR *)flatPtr );
|
|
}
|
|
|
|
/* Call 32-bit routine */
|
|
|
|
return target( lpBuff, dwUserDefined );
|
|
}
|
|
|
|
/****************************************************************************
|
|
* UTGlue32
|
|
*/
|
|
static DWORD WINAPI UTGlue32( FARPROC16 target, LPVOID lpBuff, DWORD dwUserDefined,
|
|
LPVOID translationList[] )
|
|
{
|
|
SEGPTR segBuff, *segptrList = NULL;
|
|
INT i, nList = 0;
|
|
DWORD retv;
|
|
WORD args[4];
|
|
|
|
/* Convert arguments to SEGPTRs */
|
|
|
|
if ( translationList )
|
|
for ( nList = 0; translationList[nList]; nList++ )
|
|
;
|
|
|
|
if ( nList )
|
|
{
|
|
segptrList = HeapAlloc( GetProcessHeap(), 0, sizeof(SEGPTR)*nList );
|
|
if ( !segptrList )
|
|
{
|
|
FIXME("Unable to allocate segptrList!\n" );
|
|
return 0;
|
|
}
|
|
|
|
for ( i = 0; i < nList; i++ )
|
|
segptrList[i] = *(SEGPTR *)translationList[i]
|
|
= MapLS( *(LPVOID *)translationList[i] );
|
|
}
|
|
|
|
segBuff = MapLS( lpBuff );
|
|
|
|
/* Call 16-bit routine */
|
|
|
|
args[3] = SELECTOROF(segBuff);
|
|
args[2] = OFFSETOF(segBuff);
|
|
args[1] = HIWORD(dwUserDefined);
|
|
args[0] = LOWORD(dwUserDefined);
|
|
WOWCallback16Ex( (DWORD)target, WCB16_PASCAL, sizeof(args), args, &retv );
|
|
|
|
/* Free temporary selectors */
|
|
|
|
UnMapLS( segBuff );
|
|
|
|
if ( nList )
|
|
{
|
|
for ( i = 0; i < nList; i++ )
|
|
UnMapLS( segptrList[i] );
|
|
|
|
HeapFree( GetProcessHeap(), 0, segptrList );
|
|
}
|
|
|
|
return retv;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* UTAlloc
|
|
*/
|
|
static UTINFO *UTAlloc( HMODULE hModule, HMODULE16 hModule16,
|
|
FARPROC16 target16, FARPROC target32 )
|
|
{
|
|
static FARPROC16 UTGlue16_Segptr = NULL;
|
|
UTINFO *ut;
|
|
|
|
if ( !UTGlue16_Segptr )
|
|
{
|
|
HMODULE16 hModule = GetModuleHandle16( "KERNEL" );
|
|
UTGlue16_Segptr = GetProcAddress16( hModule, "UTGlue16" );
|
|
if ( !UTGlue16_Segptr ) return NULL;
|
|
}
|
|
|
|
ut = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(UTINFO) );
|
|
if ( !ut ) return NULL;
|
|
|
|
ut->hModule = hModule;
|
|
ut->hModule16 = hModule16;
|
|
|
|
ut->ut16.popl_eax = 0x58;
|
|
ut->ut16.pushl = 0x68;
|
|
ut->ut16.target = (DWORD)target32;
|
|
ut->ut16.pushl_eax = 0x50;
|
|
ut->ut16.ljmp = 0xea;
|
|
ut->ut16.utglue16 = (DWORD)UTGlue16_Segptr;
|
|
|
|
ut->ut32.popl_eax = 0x58;
|
|
ut->ut32.pushl = 0x68;
|
|
ut->ut32.target = (DWORD)target16;
|
|
ut->ut32.pushl_eax = 0x50;
|
|
ut->ut32.jmp = 0xe9;
|
|
ut->ut32.utglue32 = (DWORD)UTGlue32 - ((DWORD)&ut->ut32.utglue32 + sizeof(DWORD));
|
|
|
|
ut->next = UT_head;
|
|
UT_head = ut;
|
|
|
|
return ut;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* UTFree
|
|
*/
|
|
static void UTFree( UTINFO *ut )
|
|
{
|
|
UTINFO **ptr;
|
|
|
|
for ( ptr = &UT_head; *ptr; ptr = &(*ptr)->next )
|
|
if ( *ptr == ut )
|
|
{
|
|
*ptr = ut->next;
|
|
break;
|
|
}
|
|
|
|
HeapFree( GetProcessHeap(), 0, ut );
|
|
}
|
|
|
|
/****************************************************************************
|
|
* UTFind
|
|
*/
|
|
static UTINFO *UTFind( HMODULE hModule )
|
|
{
|
|
UTINFO *ut;
|
|
|
|
for ( ut = UT_head; ut; ut =ut->next )
|
|
if ( ut->hModule == hModule )
|
|
break;
|
|
|
|
return ut;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* UTRegister (KERNEL32.@)
|
|
*/
|
|
BOOL WINAPI UTRegister( HMODULE hModule, LPSTR lpsz16BITDLL,
|
|
LPSTR lpszInitName, LPSTR lpszProcName,
|
|
FARPROC *ppfn32Thunk, FARPROC pfnUT32CallBack,
|
|
LPVOID lpBuff )
|
|
{
|
|
UTINFO *ut;
|
|
HMODULE16 hModule16;
|
|
FARPROC16 target16, init16;
|
|
|
|
/* Load 16-bit DLL and get UTProc16 entry point */
|
|
|
|
if ( (hModule16 = LoadLibrary16( lpsz16BITDLL )) <= 32
|
|
|| (target16 = GetProcAddress16( hModule16, lpszProcName )) == 0 )
|
|
return FALSE;
|
|
|
|
/* Allocate UTINFO struct */
|
|
|
|
RtlAcquirePebLock();
|
|
if ( (ut = UTFind( hModule )) != NULL )
|
|
ut = NULL;
|
|
else
|
|
ut = UTAlloc( hModule, hModule16, target16, pfnUT32CallBack );
|
|
RtlReleasePebLock();
|
|
|
|
if ( !ut )
|
|
{
|
|
FreeLibrary16( hModule16 );
|
|
return FALSE;
|
|
}
|
|
|
|
/* Call UTInit16 if present */
|
|
|
|
if ( lpszInitName
|
|
&& (init16 = GetProcAddress16( hModule16, lpszInitName )) != 0 )
|
|
{
|
|
SEGPTR callback = MapLS( &ut->ut16 );
|
|
SEGPTR segBuff = MapLS( lpBuff );
|
|
WORD args[4];
|
|
DWORD ret;
|
|
|
|
args[3] = SELECTOROF(callback);
|
|
args[2] = OFFSETOF(callback);
|
|
args[1] = SELECTOROF(segBuff);
|
|
args[0] = OFFSETOF(segBuff);
|
|
WOWCallback16Ex( (DWORD)init16, WCB16_PASCAL, sizeof(args), args, &ret );
|
|
UnMapLS( segBuff );
|
|
UnMapLS( callback );
|
|
if (!ret)
|
|
{
|
|
UTUnRegister( hModule );
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/* Return 32-bit thunk */
|
|
|
|
*ppfn32Thunk = (FARPROC) &ut->ut32;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* UTUnRegister (KERNEL32.@)
|
|
*/
|
|
VOID WINAPI UTUnRegister( HMODULE hModule )
|
|
{
|
|
UTINFO *ut;
|
|
HMODULE16 hModule16 = 0;
|
|
|
|
RtlAcquirePebLock();
|
|
ut = UTFind( hModule );
|
|
if ( !ut )
|
|
{
|
|
hModule16 = ut->hModule16;
|
|
UTFree( ut );
|
|
}
|
|
RtlReleasePebLock();
|
|
|
|
if ( hModule16 )
|
|
FreeLibrary16( hModule16 );
|
|
}
|
|
|
|
/****************************************************************************
|
|
* UTInit (KERNEL.493)
|
|
*/
|
|
WORD WINAPI UTInit16( DWORD x1, DWORD x2, DWORD x3, DWORD x4 )
|
|
{
|
|
FIXME("(%08lx, %08lx, %08lx, %08lx): stub\n", x1, x2, x3, x4 );
|
|
return 0;
|
|
}
|