Implemented (partially) the KERNEL Thunklet API and Callback Client

API (KERNEL.560-568,604-612,619-622).
Added stubs for K228, K237, KERNEL.365, KERNEL.447.
This commit is contained in:
Ulrich Weigand 1998-10-11 19:26:00 +00:00 committed by Alexandre Julliard
parent f276a7d441
commit 5efaf50ed5
4 changed files with 587 additions and 28 deletions

View File

@ -234,7 +234,7 @@ file krnl386.exe
225 pascal RegQueryValueEx(long str ptr ptr ptr ptr) RegQueryValueEx16 225 pascal RegQueryValueEx(long str ptr ptr ptr ptr) RegQueryValueEx16
226 pascal RegSetValueEx(long str long long ptr long) RegSetValueEx16 226 pascal RegSetValueEx(long str long long ptr long) RegSetValueEx16
227 pascal RegFlushKey(long) RegFlushKey 227 pascal RegFlushKey(long) RegFlushKey
228 stub K228 228 pascal16 K228(word) GetExePtr
229 pascal16 K229(long) Local32GetSegment 229 pascal16 K229(long) Local32GetSegment
230 pascal GlobalSmartPageLock(word) GlobalPageLock #? 230 pascal GlobalSmartPageLock(word) GlobalPageLock #?
231 stub GlobalSmartPageUnlock 231 stub GlobalSmartPageUnlock
@ -243,7 +243,7 @@ file krnl386.exe
234 stub RegSaveKey 234 stub RegSaveKey
235 stub InvalidateNlsCache 235 stub InvalidateNlsCache
236 stub GetProductName 236 stub GetProductName
237 stub K237 237 return K237 0 0
# 262-274 are WinNT extensions; those are not present in Win95 # 262-274 are WinNT extensions; those are not present in Win95
@ -307,7 +307,7 @@ file krnl386.exe
360 pascal16 OpenFileEx(str ptr word) OpenFile16 360 pascal16 OpenFileEx(str ptr word) OpenFile16
361 return PIGLET_361 0 0 361 return PIGLET_361 0 0
362 stub ThunkTerminateProcess 362 stub ThunkTerminateProcess
365 stub KERNEL_365 365 register KERNEL_365(word word) KERNEL_365
# 403-404 are common to all versions # 403-404 are common to all versions
@ -351,13 +351,13 @@ file krnl386.exe
444 stub KERNEL_444 # Local32 ??? 444 stub KERNEL_444 # Local32 ???
445 stub KERNEL_445 # Local32 ??? 445 stub KERNEL_445 # Local32 ???
446 stub KERNEL_446 # Local32 ??? 446 stub KERNEL_446 # Local32 ???
447 stub KERNEL_447 447 return KERNEL_447 0 0
448 stub KERNEL_448 448 stub KERNEL_448
449 pascal GetpWin16Lock() GetpWin16Lock16 449 pascal GetpWin16Lock() GetpWin16Lock16
450 pascal VWin32_EventWait(long) VWin32_EventWait 450 pascal VWin32_EventWait(long) VWin32_EventWait
451 pascal VWin32_EventSet(long) VWin32_EventSet 451 pascal VWin32_EventSet(long) VWin32_EventSet
452 pascal LoadLibrary32(str) LoadLibrary32A 452 pascal LoadLibrary32(str) LoadLibrary32A
453 pascal GetProcAddress32(long str) GetProcAddress32 453 pascal GetProcAddress32(long str) WIN16_GetProcAddress32
454 equate __FLATCS 0 # initialized by BUILTIN_Init() 454 equate __FLATCS 0 # initialized by BUILTIN_Init()
455 equate __FLATDS 0 # initialized by BUILTIN_Init() 455 equate __FLATDS 0 # initialized by BUILTIN_Init()
456 pascal DefResourceHandler(word word word) NE_DefResourceHandler 456 pascal DefResourceHandler(word word word) NE_DefResourceHandler
@ -455,15 +455,14 @@ file krnl386.exe
#541 stub KERNEL_541 #541 stub KERNEL_541
542 stub KERNEL_542 542 stub KERNEL_542
543 stub KERNEL_543 543 stub KERNEL_543
560 stub KERNEL_560 # (thunklet) # InitThunkletHandler 560 pascal SetThunkletCallbackGlue(long segptr) SetThunkletCallbackGlue
561 stub KERNEL_561 # (thunklet) # AllocLSThunklet 561 pascal AllocLSThunkletCallback(segptr long) AllocLSThunkletCallback
562 stub KERNEL_562 # (thunklet) # AllocSLThunklet 562 pascal AllocSLThunkletCallback(long long) AllocSLThunkletCallback
563 stub KERNEL_563 # (thunklet) # FindSLThunklet 563 pascal FindLSThunkletCallback(segptr long) FindLSThunkletCallback
564 stub KERNEL_564 # (thunklet) # FindLSThunklet 564 pascal FindSLThunkletCallback(long long) FindSLThunkletCallback
565 stub KERNEL_565 # (thunklet) # AllocLSThunklet_Special 566 stub KERNEL_566 # (thunklet) FIXME!!!
566 stub KERNEL_566 # (thunklet) # AllocSLThunklet_Special 567 pascal AllocLSThunkletCallbackEx(segptr long word) AllocLSThunkletCallbackEx
567 stub KERNEL_567 # (thunklet) # AllocLSThunkletEx 568 pascal AllocSLThunkletCallbackEx(long long word) AllocSLThunkletCallbackEx
568 stub KERNEL_568 # (thunklet) # AllocSLThunkletEx
# 600-653 are Win95 only # 600-653 are Win95 only
@ -472,25 +471,25 @@ file krnl386.exe
601 stub KERNEL_601 # FreeSelector (?) 601 stub KERNEL_601 # FreeSelector (?)
602 stub GetCurrentHInstanceDS 602 stub GetCurrentHInstanceDS
603 stub KERNEL_603 # OutputDebugString (?) 603 stub KERNEL_603 # OutputDebugString (?)
604 stub KERNEL_604 # (cbclient) # Thunk_CBClient 604 register CBClientGlueSL() CBClientGlueSL
605 stub KERNEL_605 # (thunklet) # AllocSLThunklet 605 pascal AllocSLThunkletCallback(long long) AllocSLThunkletCallback
606 stub KERNEL_606 # (thunklet) # AllocLSThunklet 606 pascal AllocLSThunkletCallback(segptr long) AllocLSThunkletCallback
607 pascal KERNEL_607(long long long) _KERNEL_607 # AllocLSThunklet_Systhunk 607 pascal AllocLSThunkletSysthunk(segptr long long) AllocLSThunkletSysthunk
608 pascal KERNEL_608(long long long) _KERNEL_608 # AllocSLThunklet_Systhunk 608 pascal AllocSLThunkletSysthunk(long segptr long) AllocSLThunkletSysthunk
609 stub KERNEL_609 # (thunklet) # FindSLThunklet 609 pascal FindLSThunkletCallback(segptr long) FindLSThunkletCallback
610 stub KERNEL_610 # (thunklet) # FindLSThunklet 610 pascal FindSLThunkletCallback(long long) FindSLThunkletCallback
611 pascal16 KERNEL_611(long long) _KERNEL_611 # FreeThunklet 611 return FreeThunklet 8 0
612 pascal16 KERNEL_612(ptr) _KERNEL_612 # IsSLThunklet 612 pascal16 IsSLThunklet(ptr) IsSLThunklet
613 stub KERNEL_613 # (cbclient) 613 stub KERNEL_613 # (cbclient)
614 stub KERNEL_614 # (cbclient) 614 stub KERNEL_614 # (cbclient)
615 stub KERNEL_615 # (cbclient) 615 stub KERNEL_615 # (cbclient)
616 stub KERNEL_616 # (cbclient) 616 stub KERNEL_616 # (cbclient)
617 stub KERNEL_617 # (cbclient) 617 stub KERNEL_617 # (cbclient)
618 stub KERNEL_618 # (cbclient) 618 stub KERNEL_618 # (cbclient)
619 pascal16 RegisterCBClient(word long long) RegisterCBClient 619 pascal16 RegisterCBClient(word ptr long) RegisterCBClient
620 stub KERNEL_620 # (cbclient) 620 register CBClientThunkSL() CBClientThunkSL
621 stub KERNEL_621 # (cbclient) 621 stub KERNEL_621 # (cbclient)
622 stub UnRegisterCBClient 622 pascal16 UnRegisterCBClient(word ptr long) UnRegisterCBClient
623 pascal16 InitCBClient(long) InitCBClient 623 pascal16 InitCBClient(long) InitCBClient
624 pascal SetFastQueue(long long) SetFastQueue 624 pascal SetFastQueue(long long) SetFastQueue
625 pascal GetFastQueue() GetFastQueue 625 pascal GetFastQueue() GetFastQueue

View File

@ -29,9 +29,11 @@ BOOL32 RELAY_Init(void)
extern void CALLTO16_Start(), CALLTO16_End(); extern void CALLTO16_Start(), CALLTO16_End();
extern void CALLTO16_Ret_word(), CALLTO16_Ret_long(); extern void CALLTO16_Ret_word(), CALLTO16_Ret_long();
extern void CALLTO16_Ret_eax(); extern void CALLTO16_Ret_eax();
extern void CALL32_CBClient_Ret();
extern DWORD CALLTO16_RetAddr_word; extern DWORD CALLTO16_RetAddr_word;
extern DWORD CALLTO16_RetAddr_long; extern DWORD CALLTO16_RetAddr_long;
extern DWORD CALLTO16_RetAddr_eax; extern DWORD CALLTO16_RetAddr_eax;
extern DWORD CALL32_CBClient_RetAddr;
codesel = GLOBAL_CreateBlock( GMEM_FIXED, (void *)CALLTO16_Start, codesel = GLOBAL_CreateBlock( GMEM_FIXED, (void *)CALLTO16_Start,
(int)CALLTO16_End - (int)CALLTO16_Start, (int)CALLTO16_End - (int)CALLTO16_Start,
@ -46,6 +48,8 @@ BOOL32 RELAY_Init(void)
codesel ); codesel );
CALLTO16_RetAddr_eax =MAKELONG( (int)CALLTO16_Ret_eax -(int)CALLTO16_Start, CALLTO16_RetAddr_eax =MAKELONG( (int)CALLTO16_Ret_eax -(int)CALLTO16_Start,
codesel ); codesel );
CALL32_CBClient_RetAddr =
MAKELONG( (int)CALL32_CBClient_Ret -(int)CALLTO16_Start, codesel );
/* Create built-in modules */ /* Create built-in modules */
if (!BUILTIN_Init()) return FALSE; if (!BUILTIN_Init()) return FALSE;

View File

@ -134,6 +134,8 @@ static BOOL32 WINAPI THUNK_WOWCallback16Ex( FARPROC16,DWORD,DWORD,
/* TASK_Reschedule() 16-bit entry point */ /* TASK_Reschedule() 16-bit entry point */
static FARPROC16 TASK_RescheduleProc; static FARPROC16 TASK_RescheduleProc;
static BOOL32 THUNK_ThunkletInit( void );
extern void CallFrom16_p_long_wwwll(void); extern void CallFrom16_p_long_wwwll(void);
/* Callbacks function table for the emulator */ /* Callbacks function table for the emulator */
@ -177,10 +179,10 @@ BOOL32 THUNK_Init(void)
Callbacks = &CALLBACK_EmulatorTable; Callbacks = &CALLBACK_EmulatorTable;
/* Get the 16-bit reschedule function pointer */ /* Get the 16-bit reschedule function pointer */
TASK_RescheduleProc = MODULE_GetWndProcEntry16( "TASK_Reschedule" ); TASK_RescheduleProc = MODULE_GetWndProcEntry16( "TASK_Reschedule" );
return TRUE; /* Initialize Thunklets */
return THUNK_ThunkletInit();
} }
/*********************************************************************** /***********************************************************************
* THUNK_Alloc * THUNK_Alloc
*/ */
@ -935,3 +937,399 @@ WOW16Call(WORD x,WORD y,WORD z) {
DPRINTF(") calling address was 0x%08lx\n",calladdr); DPRINTF(") calling address was 0x%08lx\n",calladdr);
return 0; return 0;
} }
/***********************************************************************
* 16<->32 Thunklet/Callback API:
*/
#pragma pack(1)
typedef struct _THUNKLET
{
BYTE prefix_target;
BYTE pushl_target;
DWORD target;
BYTE prefix_relay;
BYTE pushl_relay;
DWORD relay;
BYTE jmp_glue;
DWORD glue;
BYTE type;
HINSTANCE16 owner;
struct _THUNKLET *next;
} THUNKLET;
#pragma pack(4)
#define THUNKLET_TYPE_LS 1
#define THUNKLET_TYPE_SL 2
static HANDLE32 ThunkletHeap = 0;
static THUNKLET *ThunkletAnchor = NULL;
static FARPROC32 ThunkletSysthunkGlueLS = 0;
static SEGPTR ThunkletSysthunkGlueSL = 0;
static FARPROC32 ThunkletCallbackGlueLS = 0;
static SEGPTR ThunkletCallbackGlueSL = 0;
/***********************************************************************
* THUNK_ThunkletInit
*/
static BOOL32 THUNK_ThunkletInit( void )
{
LPBYTE thunk;
ThunkletHeap = HeapCreate(HEAP_WINE_SEGPTR | HEAP_WINE_CODE16SEG, 0, 0);
if (!ThunkletHeap) return FALSE;
thunk = HeapAlloc( ThunkletHeap, 0, 5 );
if (!thunk) return FALSE;
ThunkletSysthunkGlueLS = (FARPROC32)thunk;
*thunk++ = 0x58; /* popl eax */
*thunk++ = 0xC3; /* ret */
ThunkletSysthunkGlueSL = HEAP_GetSegptr( ThunkletHeap, 0, thunk );
*thunk++ = 0x66; *thunk++ = 0x58; /* popl eax */
*thunk++ = 0xCB; /* lret */
return TRUE;
}
/***********************************************************************
* SetThunkletCallbackGlue (KERNEL.560)
*/
void WINAPI SetThunkletCallbackGlue( FARPROC32 glueLS, SEGPTR glueSL )
{
ThunkletCallbackGlueLS = glueLS;
ThunkletCallbackGlueSL = glueSL;
}
/***********************************************************************
* THUNK_FindThunklet
*/
THUNKLET *THUNK_FindThunklet( DWORD target, DWORD relay,
DWORD glue, BYTE type )
{
THUNKLET *thunk;
for (thunk = ThunkletAnchor; thunk; thunk = thunk->next)
if ( thunk->type == type
&& thunk->target == target
&& thunk->relay == relay
&& thunk->glue == glue )
return thunk;
return NULL;
}
/***********************************************************************
* THUNK_AllocLSThunklet
*/
FARPROC32 THUNK_AllocLSThunklet( SEGPTR target, DWORD relay,
FARPROC32 glue, HTASK16 owner )
{
THUNKLET *thunk = THUNK_FindThunklet( (DWORD)target, relay, (DWORD)glue,
THUNKLET_TYPE_LS );
if (!thunk)
{
TDB *pTask = (TDB*)GlobalLock16( owner );
if ( !(thunk = HeapAlloc( ThunkletHeap, 0, sizeof(THUNKLET) )) )
return 0;
thunk->prefix_target = thunk->prefix_relay = 0x90;
thunk->pushl_target = thunk->pushl_relay = 0x68;
thunk->jmp_glue = 0xE9;
thunk->target = (DWORD)target;
thunk->relay = (DWORD)relay;
thunk->glue = (DWORD)glue - (DWORD)&thunk->owner;
thunk->type = THUNKLET_TYPE_LS;
thunk->owner = pTask? pTask->hInstance : 0;
thunk->next = ThunkletAnchor;
ThunkletAnchor = thunk;
}
return (FARPROC32)thunk;
}
/***********************************************************************
* THUNK_AllocSLThunklet
*/
SEGPTR THUNK_AllocSLThunklet( FARPROC32 target, DWORD relay,
SEGPTR glue, HTASK16 owner )
{
THUNKLET *thunk = THUNK_FindThunklet( (DWORD)target, relay, (DWORD)glue,
THUNKLET_TYPE_SL );
if (!thunk)
{
TDB *pTask = (TDB*)GlobalLock16( owner );
if ( !(thunk = HeapAlloc( ThunkletHeap, 0, sizeof(THUNKLET) )) )
return 0;
thunk->prefix_target = thunk->prefix_relay = 0x66;
thunk->pushl_target = thunk->pushl_relay = 0x68;
thunk->jmp_glue = 0xEA;
thunk->target = (DWORD)target;
thunk->relay = (DWORD)relay;
thunk->glue = (DWORD)glue;
thunk->type = THUNKLET_TYPE_SL;
thunk->owner = pTask? pTask->hInstance : 0;
thunk->next = ThunkletAnchor;
ThunkletAnchor = thunk;
}
return HEAP_GetSegptr( ThunkletHeap, 0, thunk );
}
/**********************************************************************
* IsLSThunklet
*/
BOOL16 WINAPI IsLSThunklet( THUNKLET *thunk )
{
return thunk->prefix_target == 0x90 && thunk->pushl_target == 0x68
&& thunk->prefix_relay == 0x90 && thunk->pushl_relay == 0x68
&& thunk->jmp_glue == 0xE9 && thunk->type == THUNKLET_TYPE_LS;
}
/**********************************************************************
* IsSLThunklet (KERNEL.612)
*/
BOOL16 WINAPI IsSLThunklet( THUNKLET *thunk )
{
return thunk->prefix_target == 0x66 && thunk->pushl_target == 0x68
&& thunk->prefix_relay == 0x66 && thunk->pushl_relay == 0x68
&& thunk->jmp_glue == 0xEA && thunk->type == THUNKLET_TYPE_SL;
}
/***********************************************************************
* AllocLSThunkletSysthunk (KERNEL.607)
*/
FARPROC32 WINAPI AllocLSThunkletSysthunk( SEGPTR target,
FARPROC32 relay, DWORD dummy )
{
return THUNK_AllocLSThunklet( (SEGPTR)relay, (DWORD)target,
ThunkletSysthunkGlueLS, GetCurrentTask() );
}
/***********************************************************************
* AllocSLThunkletSysthunk (KERNEL.608)
*/
SEGPTR WINAPI AllocSLThunkletSysthunk( FARPROC32 target,
SEGPTR relay, DWORD dummy )
{
return THUNK_AllocSLThunklet( (FARPROC32)relay, (DWORD)target,
ThunkletSysthunkGlueSL, GetCurrentTask() );
}
/***********************************************************************
* AllocLSThunkletCallbackEx (KERNEL.567)
*/
FARPROC32 WINAPI AllocLSThunkletCallbackEx( SEGPTR target,
DWORD relay, HTASK16 task )
{
THUNKLET *thunk = (THUNKLET *)target;
if ( IsSLThunklet( thunk ) && thunk->relay == relay
&& thunk->glue == (DWORD)ThunkletCallbackGlueSL )
return (FARPROC32)thunk->target;
return THUNK_AllocLSThunklet( target, relay,
ThunkletCallbackGlueLS, task );
}
/***********************************************************************
* AllocSLThunkletCallbackEx (KERNEL.568)
*/
SEGPTR WINAPI AllocSLThunkletCallbackEx( FARPROC32 target,
DWORD relay, HTASK16 task )
{
THUNKLET *thunk = (THUNKLET *)target;
if ( IsLSThunklet( thunk ) && thunk->relay == relay
&& thunk->glue == (DWORD)ThunkletCallbackGlueLS )
return (SEGPTR)thunk->target;
return THUNK_AllocSLThunklet( target, relay,
ThunkletCallbackGlueSL, task );
}
/***********************************************************************
* AllocLSThunkletCallback (KERNEL.561) (KERNEL.606)
*/
FARPROC32 WINAPI AllocLSThunkletCallback( SEGPTR target, DWORD relay )
{
return AllocLSThunkletCallbackEx( target, relay, GetCurrentTask() );
}
/***********************************************************************
* AllocSLThunkletCallback (KERNEL.562) (KERNEL.605)
*/
SEGPTR WINAPI AllocSLThunkletCallback( FARPROC32 target, DWORD relay )
{
return AllocSLThunkletCallbackEx( target, relay, GetCurrentTask() );
}
/***********************************************************************
* FindLSThunkletCallback (KERNEL.563) (KERNEL.609)
*/
FARPROC32 WINAPI FindLSThunkletCallback( SEGPTR target, DWORD relay )
{
THUNKLET *thunk = (THUNKLET *)PTR_SEG_TO_LIN( target );
if ( thunk && IsSLThunklet( thunk ) && thunk->relay == relay
&& thunk->glue == (DWORD)ThunkletCallbackGlueSL )
return (FARPROC32)thunk->target;
thunk = THUNK_FindThunklet( (DWORD)target, relay,
(DWORD)ThunkletCallbackGlueLS,
THUNKLET_TYPE_LS );
return (FARPROC32)thunk;
}
/***********************************************************************
* FindSLThunkletCallback (KERNEL.564) (KERNEL.610)
*/
SEGPTR WINAPI FindSLThunkletCallback( FARPROC32 target, DWORD relay )
{
THUNKLET *thunk = (THUNKLET *)target;
if ( thunk && IsLSThunklet( thunk ) && thunk->relay == relay
&& thunk->glue == (DWORD)ThunkletCallbackGlueLS )
return (SEGPTR)thunk->target;
thunk = THUNK_FindThunklet( (DWORD)target, relay,
(DWORD)ThunkletCallbackGlueSL,
THUNKLET_TYPE_SL );
return HEAP_GetSegptr( ThunkletHeap, 0, thunk );
}
/***********************************************************************
* Callback Client API
*/
#define N_CBC_FIXED 20
#define N_CBC_VARIABLE 10
#define N_CBC_TOTAL (N_CBC_FIXED + N_CBC_VARIABLE)
static SEGPTR *CBClientRelay16[ N_CBC_TOTAL ];
static FARPROC32 *CBClientRelay32[ N_CBC_TOTAL ];
/***********************************************************************
* RegisterCBClient (KERNEL.619)
*/
INT16 WINAPI RegisterCBClient( INT16 wCBCId,
SEGPTR *relay16, FARPROC32 *relay32 )
{
/* Search for free Callback ID */
if ( wCBCId == -1 )
for ( wCBCId = N_CBC_FIXED; wCBCId < N_CBC_TOTAL; wCBCId++ )
if ( !CBClientRelay16[ wCBCId ] )
break;
/* Register Callback ID */
if ( wCBCId > 0 && wCBCId < N_CBC_TOTAL )
{
CBClientRelay16[ wCBCId ] = relay16;
CBClientRelay32[ wCBCId ] = relay32;
}
else
wCBCId = 0;
return wCBCId;
}
/***********************************************************************
* UnRegisterCBClient (KERNEL.622)
*/
INT16 WINAPI UnRegisterCBClient( INT16 wCBCId,
SEGPTR *relay16, FARPROC32 *relay32 )
{
if ( wCBCId >= N_CBC_FIXED && wCBCId < N_CBC_TOTAL
&& CBClientRelay16[ wCBCId ] == relay16
&& CBClientRelay32[ wCBCId ] == relay32 )
{
CBClientRelay16[ wCBCId ] = 0;
CBClientRelay32[ wCBCId ] = 0;
}
else
wCBCId = 0;
return wCBCId;
}
/***********************************************************************
* InitCBClient (KERNEL.623)
*/
void WINAPI InitCBClient( FARPROC32 glueLS )
{
HMODULE16 kernel = GetModuleHandle16( "KERNEL" );
SEGPTR glueSL = (SEGPTR)WIN32_GetProcAddress16( kernel, (LPCSTR)604 );
SetThunkletCallbackGlue( glueLS, glueSL );
}
/***********************************************************************
* CBClientGlueSL (KERNEL.604)
*/
void WINAPI CBClientGlueSL( CONTEXT *context )
{
/* Create stack frame */
SEGPTR stackSeg = STACK16_PUSH( THREAD_Current(), 12 );
LPWORD stackLin = PTR_SEG_TO_LIN( stackSeg );
SEGPTR glue;
stackLin[3] = BP_reg( context );
stackLin[2] = SI_reg( context );
stackLin[1] = DI_reg( context );
stackLin[0] = DS_reg( context );
BP_reg( context ) = OFFSETOF( stackSeg ) + 6;
SP_reg( context ) = OFFSETOF( stackSeg ) - 4;
GS_reg( context ) = 0;
/* Jump to 16-bit relay code */
glue = CBClientRelay16[ stackLin[5] ][ stackLin[4] ];
CS_reg ( context ) = SELECTOROF( glue );
EIP_reg( context ) = OFFSETOF ( glue );
}
/***********************************************************************
* CBClientThunkSL (KERNEL.620)
*/
void WINAPI CBClientThunkSL( CONTEXT *context )
{
/* Call 32-bit relay code */
extern DWORD WINAPI CALL32_CBClient( FARPROC32 proc, LPWORD args );
LPWORD args = PTR_SEG_OFF_TO_LIN( SS_reg( context ), BP_reg( context ) );
FARPROC32 proc = CBClientRelay32[ args[2] ][ args[1] ];
EAX_reg(context) = CALL32_CBClient( proc, args );
}
/***********************************************************************
* KERNEL_365 (KERNEL.365)
*
* This is declared as a register function as it has to preserve
* *all* registers, even AX/DX !
*
*/
void WINAPI KERNEL_365( CONTEXT *context )
{
LPWORD args = PTR_SEG_OFF_TO_LIN( SS_reg( context ), SP_reg( context ) );
FIXME( thunk, "(%04X, %d): stub!\n", args[3], (INT16)args[2] );
}

View File

@ -2131,6 +2131,156 @@ static void BuildRet16Func( FILE *outfile )
fprintf( outfile, "\t.text\n" ); fprintf( outfile, "\t.text\n" );
} }
/*******************************************************************
* BuildCallTo32CBClient
*
* Call a CBClient relay stub from 32-bit code (KERNEL.620).
*
* Since the relay stub is itself 32-bit, this should not be a problem;
* unfortunately, the relay stubs are expected to switch back to a
* 16-bit stack (and 16-bit code) after completion :-(
*
* This would conflict with our 16- vs. 32-bit stack handling, so
* we simply switch *back* to our 32-bit stack before returning to
* the caller ...
*
* The CBClient relay stub expects to be called with:
* - ebp pointing to the 16-bit stack at ss:bp
* - ebx pointing to a buffer containing the saved 16-bit ss:sp
*
* After completion, the stub will load ss:sp from the buffer at ebx
* and perform a far return to 16-bit code.
*
* To trick the relay stub into returning to us, we push a 16-bit
* cs:ip pair pointing to out return entry point onto the 16-bit stack,
* followed by a ss:sp pair pointing to *that* cs:ip pair.
* Our return stub thus called will then reload the 32-bit ss:esp and
* return to 32-bit code (by using and ss:esp value that we have also
* pushed onto the 16-bit stack before and a cs:eip values found at
* that position on the 32-bit stack). The layout of our
* temporary area used on the 16-bit stack is thus as follows:
*
* (ebx+12) 32-bit ss (flat)
* (ebx+8) 32-bit sp (32-bit stack pointer)
* (ebx+6) 16-bit cs (this segment)
* (ebx+4) 16-bit ip ('16-bit' return entry point)
* (ebx+2) 16-bit ss (16-bit stack segment)
* (ebx+0) 16-bit sp (points to ebx+4)
*
* The stack layout of this function:
* (ebp+12) arg ebp value to be set for relay stub
* (ebp+8) func CBClient relay stub address
* (ebp+4) ret addr
* (ebp) ebp
*/
static void BuildCallTo32CBClient( FILE *outfile )
{
/* Function header */
fprintf( outfile, "\n\t.align 4\n" );
#ifdef USE_STABS
fprintf( outfile, ".stabs \"CALL32_CBClient:F1\",36,0,0," PREFIX "CALL32_CBClient\n" );
#endif
fprintf( outfile, "\t.globl " PREFIX "CALL32_CBClient\n" );
fprintf( outfile, PREFIX "CALL32_CBClient:\n" );
/* Entry code */
fprintf( outfile, "\tpushl %%ebp\n" );
fprintf( outfile, "\tmovl %%esp,%%ebp\n" );
fprintf( outfile, "\tpushl %%edi\n" );
fprintf( outfile, "\tpushl %%esi\n" );
fprintf( outfile, "\tpushl %%ebx\n" );
/* Get the 16-bit stack */
fprintf( outfile, "\t.byte 0x64\n\tmovl (%d),%%ebx\n", STACKOFFSET);
/* Convert it to a flat address */
fprintf( outfile, "\tshldl $16,%%ebx,%%eax\n" );
fprintf( outfile, "\tandl $0xfff8,%%eax\n" );
fprintf( outfile, "\tmovl " PREFIX "ldt_copy(%%eax),%%esi\n" );
fprintf( outfile, "\tmovw %%bx,%%ax\n" );
fprintf( outfile, "\taddl %%eax,%%esi\n" );
/* Allocate temporary area (simulate STACK16_PUSH) */
fprintf( outfile, "\tpushf\n" );
fprintf( outfile, "\tcld\n" );
fprintf( outfile, "\tleal -16(%%esi), %%edi\n" );
fprintf( outfile, "\tmovl $%d, %%ecx\n", sizeof(STACK16FRAME) );
fprintf( outfile, "\trep\n\tmovsb\n" );
fprintf( outfile, "\tpopf\n" );
fprintf( outfile, "\t.byte 0x64\n\tsubw $16,(%d)\n", STACKOFFSET );
fprintf( outfile, "\tpushl %%edi\n" ); /* remember address */
/* Set up temporary area */
fprintf( outfile, "\taddl $%d, %%ebx\n", sizeof(STACK16FRAME)-16+4 );
fprintf( outfile, "\tmovl %%ebx, (%%edi)\n" );
fprintf( outfile, "\tmovl " PREFIX "CALL32_CBClient_RetAddr, %%eax\n" );
fprintf( outfile, "\tmovl %%eax, 4(%%edi)\n" );
fprintf( outfile, "\tleal -8(%%esp), %%eax\n" );
fprintf( outfile, "\tmovl %%eax, 8(%%edi)\n" );
fprintf( outfile, "\tmovl %%ss, %%ax\n" );
fprintf( outfile, "\tandl $0x0000ffff, %%eax\n" );
fprintf( outfile, "\tmovl %%eax, 12(%%edi)\n" );
/* Setup registers and call CBClient relay stub (simulating a far call) */
fprintf( outfile, "\tmovl %%edi, %%ebx\n" );
fprintf( outfile, "\tmovl 8(%%ebp), %%eax\n" );
fprintf( outfile, "\tmovl 12(%%ebp), %%ebp\n" );
fprintf( outfile, "\tpushl %%cs\n" );
fprintf( outfile, "\tcall *%%eax\n" );
/* Cleanup temporary area (simulate STACK16_POP) */
fprintf( outfile, "\tpop %%esi\n" );
fprintf( outfile, "\tpushf\n" );
fprintf( outfile, "\tstd\n" );
fprintf( outfile, "\tdec %%esi\n" );
fprintf( outfile, "\tleal 16(%%esi), %%edi\n" );
fprintf( outfile, "\tmovl $%d, %%ecx\n", sizeof(STACK16FRAME) );
fprintf( outfile, "\trep\n\tmovsb\n" );
fprintf( outfile, "\tpopf\n" );
fprintf( outfile, "\t.byte 0x64\n\taddw $16,(%d)\n", STACKOFFSET );
/* Restore registers and return */
fprintf( outfile, "\tpopl %%ebx\n" );
fprintf( outfile, "\tpopl %%esi\n" );
fprintf( outfile, "\tpopl %%edi\n" );
fprintf( outfile, "\tpopl %%ebp\n" );
fprintf( outfile, "\tret\n" );
/* '16-bit' return stub */
fprintf( outfile, "\t.globl " PREFIX "CALL32_CBClient_Ret\n" );
fprintf( outfile, PREFIX "CALL32_CBClient_Ret:\n" );
fprintf( outfile, "\tmovzwl %%sp, %%ebx\n" );
fprintf( outfile, "\tlssl %%ss:(%%ebx), %%esp\n" );
fprintf( outfile, "\tlret\n" );
/* Declare the return address variable */
fprintf( outfile, "\t.data\n" );
fprintf( outfile, "\t.globl " PREFIX "CALL32_CBClient_RetAddr\n" );
fprintf( outfile, PREFIX "CALL32_CBClient_RetAddr:\t.long 0\n" );
fprintf( outfile, "\t.text\n" );
}
/******************************************************************* /*******************************************************************
* BuildCallTo32LargeStack * BuildCallTo32LargeStack
@ -2455,6 +2605,14 @@ static int BuildCallTo16( FILE *outfile, char * outname, int argc, char *argv[]
BuildRet16Func( outfile ); BuildRet16Func( outfile );
/* Output the CBClient callback function
* (while this does not really 'call to 16-bit' code, it is placed
* here so that its 16-bit return stub is defined within the CALLTO16
* 16-bit segment)
*/
BuildCallTo32CBClient( outfile );
fprintf( outfile, "\t.globl " PREFIX "CALLTO16_End\n" ); fprintf( outfile, "\t.globl " PREFIX "CALLTO16_End\n" );
fprintf( outfile, PREFIX "CALLTO16_End:\n" ); fprintf( outfile, PREFIX "CALLTO16_End:\n" );