Commit 5efaf50e authored by Ulrich Weigand's avatar Ulrich Weigand Committed by Alexandre Julliard

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.
parent f276a7d4
......@@ -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;
......
......@@ -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" );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment