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
|
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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
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 */
|
/* 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] );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
158
tools/build.c
158
tools/build.c
|
@ -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" );
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue