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:
parent
f276a7d441
commit
5efaf50ed5
|
@ -234,7 +234,7 @@ file krnl386.exe
|
|||
225 pascal RegQueryValueEx(long str ptr ptr ptr ptr) RegQueryValueEx16
|
||||
226 pascal RegSetValueEx(long str long long ptr long) RegSetValueEx16
|
||||
227 pascal RegFlushKey(long) RegFlushKey
|
||||
228 stub K228
|
||||
228 pascal16 K228(word) GetExePtr
|
||||
229 pascal16 K229(long) Local32GetSegment
|
||||
230 pascal GlobalSmartPageLock(word) GlobalPageLock #?
|
||||
231 stub GlobalSmartPageUnlock
|
||||
|
@ -243,7 +243,7 @@ file krnl386.exe
|
|||
234 stub RegSaveKey
|
||||
235 stub InvalidateNlsCache
|
||||
236 stub GetProductName
|
||||
237 stub K237
|
||||
237 return K237 0 0
|
||||
|
||||
|
||||
# 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
|
||||
361 return PIGLET_361 0 0
|
||||
362 stub ThunkTerminateProcess
|
||||
365 stub KERNEL_365
|
||||
365 register KERNEL_365(word word) KERNEL_365
|
||||
|
||||
|
||||
# 403-404 are common to all versions
|
||||
|
@ -351,13 +351,13 @@ file krnl386.exe
|
|||
444 stub KERNEL_444 # Local32 ???
|
||||
445 stub KERNEL_445 # Local32 ???
|
||||
446 stub KERNEL_446 # Local32 ???
|
||||
447 stub KERNEL_447
|
||||
447 return KERNEL_447 0 0
|
||||
448 stub KERNEL_448
|
||||
449 pascal GetpWin16Lock() GetpWin16Lock16
|
||||
450 pascal VWin32_EventWait(long) VWin32_EventWait
|
||||
451 pascal VWin32_EventSet(long) VWin32_EventSet
|
||||
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()
|
||||
455 equate __FLATDS 0 # initialized by BUILTIN_Init()
|
||||
456 pascal DefResourceHandler(word word word) NE_DefResourceHandler
|
||||
|
@ -455,15 +455,14 @@ file krnl386.exe
|
|||
#541 stub KERNEL_541
|
||||
542 stub KERNEL_542
|
||||
543 stub KERNEL_543
|
||||
560 stub KERNEL_560 # (thunklet) # InitThunkletHandler
|
||||
561 stub KERNEL_561 # (thunklet) # AllocLSThunklet
|
||||
562 stub KERNEL_562 # (thunklet) # AllocSLThunklet
|
||||
563 stub KERNEL_563 # (thunklet) # FindSLThunklet
|
||||
564 stub KERNEL_564 # (thunklet) # FindLSThunklet
|
||||
565 stub KERNEL_565 # (thunklet) # AllocLSThunklet_Special
|
||||
566 stub KERNEL_566 # (thunklet) # AllocSLThunklet_Special
|
||||
567 stub KERNEL_567 # (thunklet) # AllocLSThunkletEx
|
||||
568 stub KERNEL_568 # (thunklet) # AllocSLThunkletEx
|
||||
560 pascal SetThunkletCallbackGlue(long segptr) SetThunkletCallbackGlue
|
||||
561 pascal AllocLSThunkletCallback(segptr long) AllocLSThunkletCallback
|
||||
562 pascal AllocSLThunkletCallback(long long) AllocSLThunkletCallback
|
||||
563 pascal FindLSThunkletCallback(segptr long) FindLSThunkletCallback
|
||||
564 pascal FindSLThunkletCallback(long long) FindSLThunkletCallback
|
||||
566 stub KERNEL_566 # (thunklet) FIXME!!!
|
||||
567 pascal AllocLSThunkletCallbackEx(segptr long word) AllocLSThunkletCallbackEx
|
||||
568 pascal AllocSLThunkletCallbackEx(long long word) AllocSLThunkletCallbackEx
|
||||
|
||||
|
||||
# 600-653 are Win95 only
|
||||
|
@ -472,25 +471,25 @@ file krnl386.exe
|
|||
601 stub KERNEL_601 # FreeSelector (?)
|
||||
602 stub GetCurrentHInstanceDS
|
||||
603 stub KERNEL_603 # OutputDebugString (?)
|
||||
604 stub KERNEL_604 # (cbclient) # Thunk_CBClient
|
||||
605 stub KERNEL_605 # (thunklet) # AllocSLThunklet
|
||||
606 stub KERNEL_606 # (thunklet) # AllocLSThunklet
|
||||
607 pascal KERNEL_607(long long long) _KERNEL_607 # AllocLSThunklet_Systhunk
|
||||
608 pascal KERNEL_608(long long long) _KERNEL_608 # AllocSLThunklet_Systhunk
|
||||
609 stub KERNEL_609 # (thunklet) # FindSLThunklet
|
||||
610 stub KERNEL_610 # (thunklet) # FindLSThunklet
|
||||
611 pascal16 KERNEL_611(long long) _KERNEL_611 # FreeThunklet
|
||||
612 pascal16 KERNEL_612(ptr) _KERNEL_612 # IsSLThunklet
|
||||
604 register CBClientGlueSL() CBClientGlueSL
|
||||
605 pascal AllocSLThunkletCallback(long long) AllocSLThunkletCallback
|
||||
606 pascal AllocLSThunkletCallback(segptr long) AllocLSThunkletCallback
|
||||
607 pascal AllocLSThunkletSysthunk(segptr long long) AllocLSThunkletSysthunk
|
||||
608 pascal AllocSLThunkletSysthunk(long segptr long) AllocSLThunkletSysthunk
|
||||
609 pascal FindLSThunkletCallback(segptr long) FindLSThunkletCallback
|
||||
610 pascal FindSLThunkletCallback(long long) FindSLThunkletCallback
|
||||
611 return FreeThunklet 8 0
|
||||
612 pascal16 IsSLThunklet(ptr) IsSLThunklet
|
||||
613 stub KERNEL_613 # (cbclient)
|
||||
614 stub KERNEL_614 # (cbclient)
|
||||
615 stub KERNEL_615 # (cbclient)
|
||||
616 stub KERNEL_616 # (cbclient)
|
||||
617 stub KERNEL_617 # (cbclient)
|
||||
618 stub KERNEL_618 # (cbclient)
|
||||
619 pascal16 RegisterCBClient(word long long) RegisterCBClient
|
||||
620 stub KERNEL_620 # (cbclient)
|
||||
619 pascal16 RegisterCBClient(word ptr long) RegisterCBClient
|
||||
620 register CBClientThunkSL() CBClientThunkSL
|
||||
621 stub KERNEL_621 # (cbclient)
|
||||
622 stub UnRegisterCBClient
|
||||
622 pascal16 UnRegisterCBClient(word ptr long) UnRegisterCBClient
|
||||
623 pascal16 InitCBClient(long) InitCBClient
|
||||
624 pascal SetFastQueue(long long) SetFastQueue
|
||||
625 pascal GetFastQueue() GetFastQueue
|
||||
|
|
|
@ -29,9 +29,11 @@ BOOL32 RELAY_Init(void)
|
|||
extern void CALLTO16_Start(), CALLTO16_End();
|
||||
extern void CALLTO16_Ret_word(), CALLTO16_Ret_long();
|
||||
extern void CALLTO16_Ret_eax();
|
||||
extern void CALL32_CBClient_Ret();
|
||||
extern DWORD CALLTO16_RetAddr_word;
|
||||
extern DWORD CALLTO16_RetAddr_long;
|
||||
extern DWORD CALLTO16_RetAddr_eax;
|
||||
extern DWORD CALL32_CBClient_RetAddr;
|
||||
|
||||
codesel = GLOBAL_CreateBlock( GMEM_FIXED, (void *)CALLTO16_Start,
|
||||
(int)CALLTO16_End - (int)CALLTO16_Start,
|
||||
|
@ -46,6 +48,8 @@ BOOL32 RELAY_Init(void)
|
|||
codesel );
|
||||
CALLTO16_RetAddr_eax =MAKELONG( (int)CALLTO16_Ret_eax -(int)CALLTO16_Start,
|
||||
codesel );
|
||||
CALL32_CBClient_RetAddr =
|
||||
MAKELONG( (int)CALL32_CBClient_Ret -(int)CALLTO16_Start, codesel );
|
||||
|
||||
/* Create built-in modules */
|
||||
if (!BUILTIN_Init()) return FALSE;
|
||||
|
|
402
if1632/thunk.c
402
if1632/thunk.c
|
@ -134,6 +134,8 @@ static BOOL32 WINAPI THUNK_WOWCallback16Ex( FARPROC16,DWORD,DWORD,
|
|||
/* TASK_Reschedule() 16-bit entry point */
|
||||
static FARPROC16 TASK_RescheduleProc;
|
||||
|
||||
static BOOL32 THUNK_ThunkletInit( void );
|
||||
|
||||
extern void CallFrom16_p_long_wwwll(void);
|
||||
|
||||
/* Callbacks function table for the emulator */
|
||||
|
@ -177,10 +179,10 @@ BOOL32 THUNK_Init(void)
|
|||
Callbacks = &CALLBACK_EmulatorTable;
|
||||
/* Get the 16-bit reschedule function pointer */
|
||||
TASK_RescheduleProc = MODULE_GetWndProcEntry16( "TASK_Reschedule" );
|
||||
return TRUE;
|
||||
/* Initialize Thunklets */
|
||||
return THUNK_ThunkletInit();
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* THUNK_Alloc
|
||||
*/
|
||||
|
@ -935,3 +937,399 @@ WOW16Call(WORD x,WORD y,WORD z) {
|
|||
DPRINTF(") calling address was 0x%08lx\n",calladdr);
|
||||
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] );
|
||||
}
|
||||
|
||||
|
|
158
tools/build.c
158
tools/build.c
|
@ -2131,6 +2131,156 @@ static void BuildRet16Func( FILE *outfile )
|
|||
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
|
||||
|
@ -2455,6 +2605,14 @@ static int BuildCallTo16( FILE *outfile, char * outname, int argc, char *argv[]
|
|||
|
||||
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, PREFIX "CALLTO16_End:\n" );
|
||||
|
||||
|
|
Loading…
Reference in New Issue