550 lines
14 KiB
NASM
550 lines
14 KiB
NASM
;---------------------------------------------------------------------------
|
|
; Optimzed Code Path - on x86 builds effectively excecutes USER32 code.
|
|
;
|
|
; Created:
|
|
; 16-DEC-93 nandurir
|
|
;---------------------------------------------------------------------------
|
|
TITLE USER5.ASM
|
|
PAGE ,132
|
|
|
|
.286p
|
|
|
|
.xlist
|
|
include ks386p.inc
|
|
.286p
|
|
NOEXTERNS=1 ; to suppress including most of the stuff in user.inc
|
|
include wow.inc
|
|
include wowusr.inc
|
|
;;;;;include cmacros.inc
|
|
include user.inc
|
|
|
|
.list
|
|
|
|
externFP WOW16Call
|
|
|
|
createSeg _TEXT,CODE,WORD,PUBLIC,CODE
|
|
createSeg _DATA,DATA,WORD,PUBLIC,DATA,DGROUP
|
|
defgrp DGROUP,DATA
|
|
|
|
externFP WowSetCompatHandle
|
|
;---------------------------------------------------------------------------
|
|
; Optimized thunks for x86 only
|
|
;
|
|
;
|
|
;---------------------------------------------------------------------------
|
|
|
|
ifndef PMODE32
|
|
|
|
USER16CLIENTTHUNK macro Iapi, api, argtypeslist, returntype, api32, apispecificcode, callserver
|
|
sBegin CODE
|
|
|
|
index = 0
|
|
IRP argtype, <argtypeslist>
|
|
index = index + 1
|
|
ENDM
|
|
|
|
IFE index
|
|
&Iapi &api, 0
|
|
ELSE
|
|
&Iapi &api
|
|
ENDIF
|
|
sEnd CODE
|
|
endm
|
|
|
|
else
|
|
|
|
externFP OutputDebugString
|
|
LOGARGS macro apiname
|
|
push dx
|
|
push ax
|
|
push cs
|
|
push OFFSET afterlog_&apiname
|
|
call OutputDebugString
|
|
pop ax
|
|
pop dx
|
|
jmp short afterlogname_&apiname
|
|
afterlog_&apiname: DB 'USER: ','&apiname','()', 0dh, 0ah, 0
|
|
afterlogname_&apiname:
|
|
|
|
|
|
endm
|
|
; flat selector values
|
|
;
|
|
|
|
FLATDS equ KGDT_R3_DATA OR RPL_MASK
|
|
FLATFS equ KGDT_R3_TEB OR RPL_MASK
|
|
|
|
; set flat ds and fs
|
|
;
|
|
|
|
SETFLATDSANDFS macro
|
|
.386p
|
|
mov ax, FLATDS
|
|
mov ds, ax
|
|
mov ax, FLATFS
|
|
mov fs, ax
|
|
endm
|
|
|
|
externFP GetSelectorBase
|
|
GETFLATADDRESS macro farpointer
|
|
; check for null
|
|
xor dx, dx
|
|
mov ax, word ptr &farpointer+2
|
|
or ax, ax
|
|
jz @F
|
|
cCall GetSelectorBase, <ax>
|
|
|
|
; check for base address 0
|
|
|
|
mov cx, ax
|
|
or cx, dx
|
|
jz @F
|
|
|
|
; now its ok
|
|
|
|
add ax, word ptr &farpointer
|
|
adc dx, 0
|
|
@@:
|
|
endm
|
|
|
|
; generates code like: parmW arg1
|
|
;
|
|
|
|
GENPARAM macro argtype, argname
|
|
parm&argtype &argname
|
|
endm
|
|
|
|
|
|
pushWORD_DWORD macro argname
|
|
movzx eax, &argname
|
|
push eax
|
|
endm
|
|
|
|
pushINT_LONG macro argname
|
|
movsx eax, &argname
|
|
push eax
|
|
endm
|
|
|
|
pushDWORD_DWORD macro argname
|
|
push dword ptr &argname
|
|
endm
|
|
|
|
pushPSZ_DWORD macro argname, apiname, argnumber
|
|
|
|
GETFLATADDRESS &argname
|
|
push dx
|
|
push ax
|
|
|
|
IFNB <apiname>
|
|
or ax, dx
|
|
jnz @F
|
|
add sp, argnumber * 4
|
|
xor eax, eax
|
|
jmp short FailCall_&apiname
|
|
@@:
|
|
ENDIF
|
|
|
|
endm
|
|
|
|
pushHHOOK_DWORD macro argname
|
|
push dword ptr -1 ; unreferenced parameter
|
|
; effectively an assertion
|
|
endm
|
|
|
|
pushARG16 macro argname
|
|
push &argname
|
|
endm
|
|
|
|
CALLORDECLARE macro typestring, api32, totalbytes
|
|
&typestring api32&@&totalbytes
|
|
endm
|
|
|
|
TESTCALLSERVERCONDITION macro
|
|
mov edx, DWORD PTR _wow16CsrFlag
|
|
test BYTE PTR [edx], 1
|
|
endm
|
|
|
|
; assumes eax is pointer to the flag
|
|
CLEARCALLSERVERCONDITION macro
|
|
mov BYTE PTR [edx], 0
|
|
endm
|
|
|
|
;--------------------------------------------------------------------------
|
|
; Iapi = either DUserThunk or UserThunk
|
|
; api = actual name
|
|
; argtypeslist = list of argument 'types' like <WORD, INT, HWND>
|
|
; api32 = this function is called instead of _Api
|
|
; apispecificcode = flag indicating additional code needed for this api.
|
|
; This is intended for handling 'compatibility'.
|
|
;
|
|
; If this argument is not blank, then there must exist a macro
|
|
; APISPECIFICCODE_api, which expands to the desired code.
|
|
; At present it is included just before the 'return' to
|
|
; the app.
|
|
;
|
|
; callserver = flag indication that it may be necessary to actually call
|
|
; USER32.
|
|
;
|
|
; If this argument is not blank, then there must exist a macro
|
|
; CALLSERVERCONDITION_api which expands to the desired code and
|
|
; clears or sets the zero flag. If ZF is clear, the actual
|
|
; thunk gets called, else nop.
|
|
;
|
|
;
|
|
; generates code similar to:
|
|
;
|
|
; externFP _Api OR Api32
|
|
; sBegin CODE
|
|
; if necessary
|
|
; FUN_WOWApi equ FUN_Api
|
|
; DUserThunk WOWApi, %(size Api16)
|
|
; endif
|
|
;
|
|
; cProc Api, <PUBLIC, FAR, PASCAL>, <ds>
|
|
; parmW arg1
|
|
; cBegin
|
|
; movzx, eax, arg1
|
|
; push eax
|
|
; call far ptr _Api OR Api32 (decorates the names)
|
|
;
|
|
; if necessary checks the callservercondtion
|
|
; resets the callservercondition
|
|
; push arg1
|
|
; call WOWApi ; the actual thunk to wow32/server
|
|
; @@:
|
|
; endif
|
|
;
|
|
; if exists, includes code in apispecificcode_api
|
|
; endif
|
|
; cEnd
|
|
; sEnd CODE
|
|
;
|
|
; - nanduri
|
|
;--------------------------------------------------------------------------
|
|
|
|
|
|
USER16CLIENTTHUNK macro Iapi, api, argtypeslist, returntype, api32, apispecificcode, callserver
|
|
|
|
;*** declare api
|
|
;
|
|
|
|
index = 0
|
|
IRP argtype, <argtypeslist>
|
|
index = index + 1
|
|
ENDM
|
|
|
|
IFB <api32>
|
|
CALLORDECLARE <externFP>, _&api, %(index*4)
|
|
ELSE
|
|
CALLORDECLARE <externFP>, _&api32, %(index*4)
|
|
ENDIF
|
|
|
|
sBegin CODE ; _&api
|
|
|
|
;*** create thunk to wow32
|
|
;
|
|
|
|
IFNB <callserver>
|
|
FUN_WOW&api equ FUN_&api
|
|
DUserThunk WOW&api, %(size api&16)
|
|
ENDIF
|
|
|
|
;*** create thea Api label
|
|
;
|
|
|
|
IFNB <api>
|
|
IFIDNI <Iapi>, <DUSERTHUNK>
|
|
cProc &api, <PUBLIC, FAR, PASCAL>, <ds>
|
|
ELSE
|
|
cProc I&api, <PUBLIC, FAR, PASCAL>, <ds>
|
|
ENDIF
|
|
ENDIF
|
|
|
|
;*** declare args
|
|
;
|
|
|
|
nargcount = 0
|
|
IRP argtype, <argtypeslist>
|
|
nargcount = nargcount + 1
|
|
IFIDNI <argtype>, <WORD>
|
|
genparam W, arg%(nargcount)
|
|
ENDIF
|
|
IFIDNI <argtype>, <INT>
|
|
genparam W, arg%(nargcount)
|
|
ENDIF
|
|
IFIDNI <argtype>, <SHORT>
|
|
genparam W, arg%(nargcount)
|
|
ENDIF
|
|
IFIDNI <argtype>, <DWORD>
|
|
genparam D, arg%(nargcount)
|
|
ENDIF
|
|
IFIDNI <argtype>, <LONG>
|
|
genparam D, arg%(nargcount)
|
|
ENDIF
|
|
IFIDNI <argtype>, <ULONG>
|
|
genparam D, arg%(nargcount)
|
|
ENDIF
|
|
IFIDNI <argtype>, <PSZ>
|
|
genparam D, arg%(nargcount)
|
|
ENDIF
|
|
IFIDNI <argtype>, <NONOPTPSZ>
|
|
genparam D, arg%(nargcount)
|
|
ENDIF
|
|
IFIDNI <argtype>, <HWND>
|
|
genparam W, arg%(nargcount)
|
|
ENDIF
|
|
IFIDNI <argtype>, <HHOOK>
|
|
genparam D, arg%(nargcount)
|
|
ENDIF
|
|
ENDM
|
|
|
|
;*** begin body
|
|
;
|
|
|
|
cBegin
|
|
|
|
;*** set 32bit registers
|
|
;
|
|
|
|
SETFLATDSANDFS
|
|
|
|
;*** push args in reverse
|
|
;
|
|
|
|
FailCall = 0
|
|
argtopush = nargcount
|
|
REPT nargcount
|
|
inputargindex = 0
|
|
IRP argtype, <argtypeslist>
|
|
inputargindex = inputargindex + 1
|
|
IFE argtopush - inputargindex
|
|
IFIDNI <argtype>, <WORD>
|
|
pushWORD_DWORD arg%argtopush
|
|
ENDIF
|
|
IFIDNI <argtype>, <INT>
|
|
pushINT_LONG arg%argtopush
|
|
ENDIF
|
|
IFIDNI <argtype>, <SHORT>
|
|
pushINT_LONG arg%argtopush
|
|
ENDIF
|
|
IFIDNI <argtype>, <DWORD>
|
|
pushDWORD_DWORD arg%argtopush
|
|
ENDIF
|
|
IFIDNI <argtype>, <LONG>
|
|
pushDWORD_DWORD arg%argtopush
|
|
ENDIF
|
|
IFIDNI <argtype>, <ULONG>
|
|
pushDWORD_DWORD arg%argtopush
|
|
ENDIF
|
|
IFIDNI <argtype>, <PSZ>
|
|
pushPSZ_DWORD arg%argtopush
|
|
ENDIF
|
|
IFIDNI <argtype>, <NONOPTPSZ>
|
|
FailCall = argtopush ; fails call if null
|
|
pushPSZ_DWORD arg%argtopush, &api, %argtopush
|
|
ENDIF
|
|
IFIDNI <argtype>, <HWND>
|
|
pushINT_LONG arg%argtopush
|
|
ENDIF
|
|
IFIDNI <argtype>, <HHOOK>
|
|
pushHHOOK_DWORD arg%argtopush
|
|
ENDIF
|
|
ENDIF
|
|
ENDM
|
|
argtopush = argtopush - 1
|
|
ENDM
|
|
|
|
;*** called user32/client api
|
|
;
|
|
|
|
IFB <api32>
|
|
CALLORDECLARE <call>, _&api, %(nargcount*4)
|
|
ELSE
|
|
CALLORDECLARE <call>, _&api32, %(nargcount*4)
|
|
ENDIF
|
|
|
|
;*** check if we ever need to call server
|
|
;*** calls the real wow thunk
|
|
|
|
IFNB <callserver>
|
|
TESTCALLSERVERCONDITION
|
|
jz @F
|
|
CLEARCALLSERVERCONDITION
|
|
index = 0;
|
|
IRP argtype, <argtypeslist>
|
|
index = index + 1
|
|
pushARG16 arg%index
|
|
ENDM
|
|
call WOW&api
|
|
@@:
|
|
ENDIF
|
|
|
|
;*** check for any api specific compatibility code to execute
|
|
;
|
|
|
|
IFNB <apispecificcode>
|
|
APISPECIFICCODE_&api
|
|
ENDIF
|
|
|
|
IF FailCall
|
|
FailCall_&api:
|
|
ENDIF
|
|
|
|
IFNB <returntype>
|
|
IRP argtype, <dword, long, ulong>
|
|
IFIDNI <returntype>, <argtype>
|
|
mov edx, eax
|
|
shr edx, 16
|
|
EXITM
|
|
ENDIF
|
|
ENDM
|
|
|
|
IFIDNI <returntype>, <boolzero>
|
|
xor ax, ax
|
|
ENDIF
|
|
|
|
ENDIF
|
|
|
|
ifdef DEBUG
|
|
;LOGARGS &api
|
|
endif
|
|
|
|
cEnd
|
|
; end body
|
|
|
|
sEnd CODE ; _&api
|
|
endm
|
|
|
|
endif ; PMODE32
|
|
|
|
assumes CS,CODE
|
|
assumes DS,DATA
|
|
assumes ES,NOTHING
|
|
|
|
;;;;;;;;;;sBegin CODE ; macro will generate this
|
|
|
|
APISPECIFICCODE_GETCLIENTRECT macro
|
|
xor eax, eax
|
|
endm
|
|
|
|
APISPECIFICCODE_GETKEYSTATE macro
|
|
mov cl, ah
|
|
and cl, 080h
|
|
or al, cl
|
|
endm
|
|
|
|
APISPECIFICCODE_GETWINDOWRECT macro
|
|
xor eax, eax
|
|
endm
|
|
|
|
; The following call is only for a dBase for Windows 5.0 bug. Notice however, that this
|
|
; means that the internal KERNEL api WowSetCompatHandle will be called for every
|
|
; single invocation of GetDlgItem, no matter what app is running. This is bad, but
|
|
; on X86 platforms we don't transition to WOW32, and the cost of testing for it
|
|
; is just about as expensive as just saving it. Still, this should be removed as
|
|
; soon as we are convinced that the dBase bug has been fixed. -NeilSa
|
|
APISPECIFICCODE_GETDLGITEM macro
|
|
push ax
|
|
call WowSetCompatHandle
|
|
endm
|
|
|
|
public _wow16gpsi
|
|
public _wow16CsrFlag
|
|
public _wow16gHighestUserAddress
|
|
|
|
sBegin CODE
|
|
_wow16gpsi DD 0
|
|
_wow16CsrFlag DD 0
|
|
_wow16gHighestUserAddress DD 0
|
|
sEnd CODE
|
|
|
|
; the following may end up calling wow32
|
|
|
|
USER16CLIENTTHUNK UserThunk, DEFHOOKPROC, <int, word, dword, hhook>, dword, WOW16DefHookProc,,srvcond
|
|
USER16CLIENTTHUNK UserThunk, ENABLEMENUITEM, <hwnd, word, word>, word,,,srvcond
|
|
USER16CLIENTTHUNK DUserThunk, GETKEYSTATE, <int>, int,, compatcode, srvcond
|
|
USER16CLIENTTHUNK UserThunk, GETKEYBOARDSTATE, <nonoptpsz>, boolzero,,,srvcond
|
|
|
|
; the following are all thunked locally
|
|
|
|
USER16CLIENTTHUNK UserThunk, CLIENTTOSCREEN, <hwnd, psz>,boolzero
|
|
USER16CLIENTTHUNK UserThunk, GETCLASSNAME, <hwnd, psz, word>, word, GETCLASSNAMEA
|
|
USER16CLIENTTHUNK UserThunk, GETCLIENTRECT, <hwnd, psz>, bool,,compatcode
|
|
USER16CLIENTTHUNK UserThunk, GETCURSORPOS, <psz>, boolzero
|
|
USER16CLIENTTHUNK DUserThunk, GETDESKTOPHWND, <>, hwnd, GETDESKTOPWINDOW
|
|
USER16CLIENTTHUNK DUserThunk, GETDESKTOPWINDOW, <>, hwnd
|
|
USER16CLIENTTHUNK UserThunk, GETDLGITEM, <hwnd, word>, hwnd,,compatcode
|
|
USER16CLIENTTHUNK UserThunk, GETMENU, <hwnd>, hmenu
|
|
USER16CLIENTTHUNK UserThunk, GETMENUITEMCOUNT, <hwnd>, int
|
|
USER16CLIENTTHUNK UserThunk, GETMENUITEMID, <hwnd, int>, uint
|
|
USER16CLIENTTHUNK UserThunk, GETMENUSTATE, <hwnd, word, word>, uint
|
|
USER16CLIENTTHUNK DUserThunk, GETNEXTWINDOW, <hwnd, word>, hwnd, GETWINDOW
|
|
USER16CLIENTTHUNK UserThunk, GETPARENT, <hwnd>, hwnd
|
|
USER16CLIENTTHUNK UserThunk, GETSUBMENU, <hwnd, int>, hmenu
|
|
USER16CLIENTTHUNK UserThunk, GETSYSCOLOR, <int>, dword
|
|
USER16CLIENTTHUNK UserThunk, GETSYSTEMMETRICS, <int>, int
|
|
USER16CLIENTTHUNK UserThunk, GETTOPWINDOW, <hwnd>, hwnd
|
|
USER16CLIENTTHUNK UserThunk, GETWINDOW, <hwnd, word>, hwnd
|
|
USER16CLIENTTHUNK UserThunk, GETWINDOWRECT, <hwnd, psz>, bool,,compatcode
|
|
USER16CLIENTTHUNK DUserThunk, ISWINDOW, <hwnd>, bool
|
|
USER16CLIENTTHUNK UserThunk, SCREENTOCLIENT, <hwnd, psz>, boolzero
|
|
ifdef DEBUG
|
|
USER16CLIENTTHUNK UserThunk, ISCHILD, <hwnd, hwnd>, bool
|
|
USER16CLIENTTHUNK UserThunk, ISICONIC, <hwnd>, bool
|
|
USER16CLIENTTHUNK UserThunk, ISWINDOWENABLED, <hwnd>, bool
|
|
USER16CLIENTTHUNK UserThunk, ISWINDOWVISIBLE, <hwnd>, bool
|
|
USER16CLIENTTHUNK UserThunk, ISZOOMED, <hwnd>, bool
|
|
else
|
|
USER16CLIENTTHUNK DUserThunk, ISCHILD, <hwnd, hwnd>, bool
|
|
USER16CLIENTTHUNK DUserThunk, ISICONIC, <hwnd>, bool
|
|
USER16CLIENTTHUNK DUserThunk, ISWINDOWENABLED, <hwnd>, bool
|
|
USER16CLIENTTHUNK DUserThunk, ISWINDOWVISIBLE, <hwnd>, bool
|
|
USER16CLIENTTHUNK DUserThunk, ISZOOMED, <hwnd>, bool
|
|
endif
|
|
|
|
|
|
;;;;;;;;;sEnd CODE ; macro will generate this
|
|
|
|
sBegin CODE
|
|
|
|
ifndef PMODE32
|
|
|
|
DUserThunk GETTICKCOUNT, 0
|
|
DUserThunk GETCURRENTTIME, 0
|
|
|
|
else
|
|
|
|
labelFP <PUBLIC, GETTICKCOUNT>
|
|
labelFP <PUBLIC, GETCURRENTTIME>
|
|
|
|
; the TickCount is accessible from client address space.
|
|
; refer sdk\inc\ntexapi.h
|
|
; - nanduri
|
|
|
|
.386p
|
|
; set 32bit ds
|
|
|
|
push ds
|
|
mov ax, FLATDS
|
|
mov ds, ax
|
|
|
|
; from sdk\inc\ntexapi.h NtGetTickCount - equivalent code
|
|
|
|
mov edx, MM_SHARED_USER_DATA_VA
|
|
mov eax, [edx].UsTickCountLow
|
|
mul dword ptr [edx].UsTickCountMultiplier
|
|
shrd eax,edx,24
|
|
|
|
mov edx, eax
|
|
shr edx, 010h
|
|
and ax, NOT GRAINYTIC_RES ; round off to lower 64 boundary
|
|
;this is a cheap implemention of WOWCF_GRAINYTICS flag
|
|
pop ds
|
|
retf
|
|
.286p
|
|
|
|
endif
|
|
|
|
sEnd CODE
|
|
end
|