Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

687 lines
15 KiB

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
thunk.s
Abstract:
Implements the API thunk that gets executed for all
re-directed APIS.
Author:
Wesley Witt (wesw) 28-June-1995
Environment:
User Mode
--*/
#include <ksmips.h>
.extern HandleDynamicDllLoadA
.extern HandleDynamicDllLoadW
.extern QueryPerformanceCounter
.extern GetApiInfo
.extern ApiCounter
.extern pGetLastError
.extern pSetLastError
.extern pTlsGetValue
.extern pTlsSetValue
.extern TlsReEnter
.extern TlsStack
#define move(r1,of1,r2,of2) lw t7,of1(r1); sw t7,of2(r2)
#define DllEnabledOffset 52
#define ApiInfoCountOffset 12
#define ApiInfoAddressOffset 4
#define ApiInfoTimeOffet 16
#define ArgSave 16
#define RaFrm 0
#define A0Frm 4
#define A1Frm 8
#define A2Frm 12
#define A3Frm 16
#define T0Frm 20
#define T1Frm 24
#define T2Frm 28
#define s7Frm 32
#define V0Frm 36
#define V1Frm 40
#define LastErrorFrm 44
#define FuncAddrFrm 48
#define Time1Frm 52
#define RaSave (RaFrm + ArgSave)
#define A0Save (A0Frm + ArgSave)
#define A1Save (A1Frm + ArgSave)
#define A2Save (A2Frm + ArgSave)
#define A3Save (A3Frm + ArgSave)
#define T0Save (T0Frm + ArgSave)
#define T1Save (T1Frm + ArgSave)
#define T2Save (T2Frm + ArgSave)
#define s7Save (s7Frm + ArgSave)
#define V0Save (V0Frm + ArgSave)
#define V1Save (V1Frm + ArgSave)
#define LastErrorSave (LastErrorFrm + ArgSave)
#define FuncAddrSave (FuncAddrFrm + ArgSave)
#define Time1Save (Time1Frm + ArgSave)
#define Time2Save (0 + ArgSave)
#define FrameSize 64
#define StackSize (FrameSize + ArgSave)
.text;
.globl ApiMonThunkComplete;
.ent ApiMonThunkComplete, 0;
ApiMonThunkComplete:;
.set noat
.set noreorder
//
// create some temporary stack
//
addiu sp,sp,-StackSize
//
// save the return value from the api
//
sw v0,V0Frm(s7)
sw v1,V1Frm(s7)
//
// save the last error value
//
lw t7,pGetLastError
jalr t7
nop
sw v0,LastErrorFrm(s7)
//
// get the final timestamp value
//
addiu a0,sp,Time2Save
jalr QueryPerformanceCounter
nop
//
// compute the time used for this api
//
lw t0,Time2Save(sp)
lw t1,Time2Save+4(sp)
lw t2,Time1Frm(s7)
lw t3,Time1Frm+4(s7)
sltu AT,t0,t2
subu t4,t0,t2
subu t5,t1,t3
subu t5,t5,AT
//
// add the result to the api's time counter
//
lw t1,T1Frm(s7)
sw t4,ApiInfoTimeOffet(t1)
sw t5,ApiInfoTimeOffet+4(t1)
//
// branch to the correct handler
//
lw t2,T2Frm(s7)
beq t2,zero,ThunkNormal
nop
ori t1,zero,1
beq t2,t1,DoLoadLibraryA
nop
ori t1,zero,2
beq t2,t1,DoLoadLibraryW
nop
ori t1,zero,3
beq t2,t1,DoFreeLibrary
nop
j ThunkNormal
DoLoadLibraryW:
lw a0,V0Frm(s7)
lw a1,A0Frm(s7)
jalr HandleDynamicDllLoadW
nop
j ThunkNormal
nop
DoLoadLibraryA:
lw a0,V0Frm(s7)
lw a1,A0Frm(s7)
jalr HandleDynamicDllLoadA
nop
j ThunkNormal
nop
DoFreeLibrary:
lw a0,A0Frm(s7)
jalr HandleDynamicDllFree
nop
j ThunkNormal
nop
ThunkNormal:
//
// do the api tracing?
//
lw t0,ApiTraceEnabled
beq t0,zero,NoTracing
nop
lw a0,T1Frm(s7)
addiu a1,sp,A0Frm
lw a2,V0Frm(s7)
jalr ApiTrace
nop
NoTracing:
//
// destroy this frame
//
or a1,zero,s7
lw a0,TlsStack
lw t7,pTlsSetValue
jalr t7
nop
//
// reset the last error value
//
lw a0,LastErrorFrm(s7)
lw t7,pSetLastError
jalr t7
nop
//
// restore the registers
//
lw ra,RaFrm(s7)
lw a0,A0Frm(s7)
lw a1,A1Frm(s7)
lw a2,A2Frm(s7)
lw a3,A3Frm(s7)
lw t0,T0Frm(s7)
lw t1,T1Frm(s7)
lw t2,T2Frm(s7)
lw v0,V0Frm(s7)
lw v1,V1Frm(s7)
lw s7,s7Frm(s7)
//
// reset the stack pointer
//
addiu sp,sp,StackSize
//
// jump back to the caller
//
jr ra
nop
.set reorder
.set at
.end ApiMonThunkComplete
//
// upon entry:
//
// t0 = DllInfo
// t1 = ApiInfo
// t2 = ApiFlag
//
.text;
.globl ApiMonThunk;
.globl Thunk_Middle;
.ent ApiMonThunk, 0;
ApiMonThunk:;
.set noat
.set noreorder
//
// create some temporary stack
//
or v0,zero,sp
addiu sp,sp,-StackSize
//
// save the requisite registers
//
sw ra,RaSave(sp)
sw a0,A0Save(sp)
sw a1,A1Save(sp)
sw a2,A2Save(sp)
sw a3,A3Save(sp)
sw t0,T0Save(sp)
sw t1,T1Save(sp)
sw t2,T2Save(sp)
sw s7,s7Save(sp)
//
// get the last error value
//
lw t7,pGetLastError
jalr t7
nop
sw v0,LastErrorSave(sp)
//
// get the reentry flag
//
lw a0,TlsReEnter
lw t7,pTlsGetValue
jalr t7
nop
//
// don't enter if disallow flag is set
//
beq v0,zero,ThunkOk
nop
DontReEnter:
//
// reset the last error value
//
lw a0,LastErrorSave(sp)
lw t7,pSetLastError
jalr t7
nop
//
// restore the registers
//
lw ra,RaSave(sp)
lw a0,A0Save(sp)
lw a1,A1Save(sp)
lw a2,A2Save(sp)
lw a3,A3Save(sp)
lw t0,T0Save(sp)
lw t1,T1Save(sp)
lw t2,T2Save(sp)
//
// reset the stack pointer
//
addiu sp,sp,StackSize
//
// jump to the real api
//
lw t0,ApiInfoAddressOffset(t1)
jr t0
nop
ThunkOk:
//
// set the disallow flag
//
ori a1,zero,1
lw a0,TlsReEnter
lw t7,pTlsSetValue
jalr t7
nop
//
// get the parallel stack pointer
//
lw a0,TlsStack
lw t7,pTlsGetValue
jalr t7
nop
//
// create a frame on the stack
//
or s7,zero,v0
addiu a1,v0,FrameSize
lw a0,TlsStack
lw t7,pTlsSetValue
jalr t7
nop
//
// move the data into the parallel stack frame
//
move ( sp, RaSave, s7, RaFrm )
move ( sp, A0Save, s7, A0Frm )
move ( sp, A1Save, s7, A1Frm )
move ( sp, A2Save, s7, A2Frm )
move ( sp, A3Save, s7, A3Frm )
move ( sp, T0Save, s7, T0Frm )
move ( sp, T1Save, s7, T1Frm )
move ( sp, T2Save, s7, T2Frm )
move ( sp, s7Save, s7, s7Frm )
move ( sp, LastErrorSave, s7, LastErrorFrm )
move ( sp, FuncAddrSave, s7, FuncAddrFrm )
//
// get the func address
//
lw t1,T1Frm(s7)
lw t0,ApiInfoAddressOffset(t1)
sw t0,FuncAddrFrm(s7)
Thunk_Middle:
//
// check to see if api counting is enabled
// if not then bypass the counting code
//
lw t0,T0Frm(s7)
lw t0,DllEnabledOffset(t0)
beq t0,zero,ThunkBypass
nop
//
// get the initial timestamp value
//
addiu a0,s7,Time1Frm
jalr QueryPerformanceCounter
nop
//
// increment the api's counter
//
lw t1,T1Frm(s7)
lw t0,ApiInfoCountOffset(t1)
addiu t0,t0,1
sw t0,ApiInfoCountOffset(t1)
//
// increment the global api counter
//
lw t0,ApiCounter
lw t3,0(t0)
addiu t3,t3,1
sw t3,0(t0)
ThunkBypass:
//
// reset the last error value
//
lw a0,LastErrorFrm(s7)
lw t7,pSetLastError
jalr t7
nop
//
// clear the disallow flag
//
or a1,zero,zero
lw a0,TlsReEnter
lw t7,pTlsSetValue
jalr t7
nop
//
// change the return address to the completion thunk
//
la ra,ApiMonThunkComplete
//
// restore the registers
//
lw a0,A0Frm(s7)
lw a1,A1Frm(s7)
lw a2,A2Frm(s7)
lw a3,A3Frm(s7)
//
// reset the stack pointer
//
addiu sp,sp,StackSize
//
// jump to the real api
//
lw t0,FuncAddrFrm(s7)
jr t0
nop
.set reorder
.set at
.end ApiMonThunk
.text;
.globl __penter;
.ent __penter, 0;
__penter:;
.set noat
.set noreorder
//
// create some temporary stack
//
or v0,zero,sp
addiu sp,sp,-StackSize
//
// save the requisite registers
//
sw ra,RaSave(sp)
sw ra,FuncAddrSave(sp)
sw a0,A0Save(sp)
sw a1,A1Save(sp)
sw a2,A2Save(sp)
sw a3,A3Save(sp)
sw t0,T0Save(sp)
sw t1,T1Save(sp)
sw t2,T2Save(sp)
sw s7,s7Save(sp)
//
// save the last error value
//
lw t7,pGetLastError
jalr t7
nop
sw v0,LastErrorSave(sp)
//
// get the parallel stack pointer
//
lw a0,TlsStack
lw t7,pTlsGetValue
jalr t7
nop
//
// bail out if the stack value is zero
//
bne v0,zero,Good_Stack
nop
//
// restore the last error value
//
lw a0,LastErrorSave(sp)
lw t7,pSetLastError
jalr t7
nop
//
// restore the registers
//
lw ra,RaSave(sp)
lw a0,A0Save(sp)
lw a1,A1Save(sp)
lw a2,A2Save(sp)
lw a3,A3Save(sp)
lw t0,T0Save(sp)
lw t1,T1Save(sp)
lw t2,T2Save(sp)
lw s7,s7Save(sp)
//
// restore the stack
//
addiu sp,sp,StackSize
//
// branch back to the caller
//
jr ra
nop
Good_Stack:
//
// create a frame on the stack
//
or s7,zero,v0
addiu a1,v0,FrameSize
lw a0,TlsStack
lw t7,pTlsSetValue
jalr t7
nop
//
// move the data into the parallel stack frame
//
move ( sp, RaSave, s7, RaFrm )
move ( sp, A0Save, s7, A0Frm )
move ( sp, A1Save, s7, A1Frm )
move ( sp, A2Save, s7, A2Frm )
move ( sp, A3Save, s7, A3Frm )
move ( sp, T0Save, s7, T0Frm )
move ( sp, T1Save, s7, T1Frm )
move ( sp, T2Save, s7, T2Frm )
move ( sp, s7Save, s7, s7Frm )
move ( sp, LastErrorSave, s7, LastErrorFrm )
move ( sp, FuncAddrSave, s7, FuncAddrFrm )
//
// get the apiinfo
//
addiu sp,sp,-28
or a0,zero,sp
addiu a0,sp,16
addiu a1,sp,20
addiu a2,sp,24
lw a3,RaFrm(s7)
jalr GetApiInfo
nop
//
// could not find the api, so punt
//
beq v0,zero,Api_NotFound
nop
//
// found it
//
lw t1,16(sp)
lw t0,20(sp)
lw t2,24(sp)
sw t0,T0Frm(s7)
sw t1,T1Frm(s7)
sw t2,T2Frm(s7)
//
// reset the stack pointer
//
addiu sp,sp,28
//
// get the return address
//
addiu t6,sp,StackSize
add t6,t6,v0
lw t7,0(t6)
sw t7,RaFrm(s7)
la t8,ApiMonThunkComplete
sw t8,0(t6)
//
// branch to the normal code path
//
la t7,Thunk_Middle
jr t7
nop
Api_NotFound:
//
// destroy this frame
//
or a1,zero,s7
lw a0,TlsStack
lw t7,pTlsSetValue
jalr t7
nop
//
// restore the last error value
//
lw a0,LastErrorFrm(s7)
lw t7,pSetLastError
jalr t7
nop
//
// restore the registers
//
lw ra,RaFrm(s7)
lw a0,A0Frm(s7)
lw a1,A1Frm(s7)
lw a2,A2Frm(s7)
lw a3,A3Frm(s7)
lw t0,T0Frm(s7)
lw t1,T1Frm(s7)
lw t2,T2Frm(s7)
lw s7,s7Frm(s7)
//
// reset the stack pointer
//
addiu sp,sp,StackSize+28
//
// branch back to the caller
//
jr ra
nop
.set reorder
.set at
.end __penter