Leaked source code of windows server 2003
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.
 
 
 
 
 
 

923 lines
30 KiB

page ,132
;------------------------------Module-Header----------------------------;
; Module Name: lock.asm ;
; ;
; Contains the ASM versions of locking routines. ;
; ;
; Copyright (c) 1992-1999 Microsoft Corporation ;
;-----------------------------------------------------------------------;
.386
.model small
assume cs:FLAT,ds:FLAT,es:FLAT,ss:FLAT
assume fs:nothing,gs:nothing
.xlist
include callconv.inc
include ks386.inc
include gdii386.inc
.list
if GDIPLUS
; See hmgrapi.cxx
else
.data
if DBG
HL_AlreadyLocked db 'HmgLock Error: GDI handle already locked by another thread',10,0
HL_OverFlowShareRef db 'Hmg Error: GDI handle share reference count over flowed',10,0
endif
_DATA SEGMENT DWORD PUBLIC 'DATA'
public _GDIpLockPrefixTable
_GDIpLockPrefixTable label dword
dd offset FLAT:Lock1
dd offset FLAT:Lock4
dd offset FLAT:Lock5
dd offset FLAT:Lock6
dd offset FLAT:Lock7
dd offset FLAT:Lock8
dd 0
_DATA ENDS
OBJECTOWNER_LOCK equ 1h ; First bit of the objectowner
OBJECTOWNER_PID equ 0fffffffeh ; The PID bits
.code
extrn _gpentHmgr:dword ; Address of ENTRY array.
extrn _gcMaxHmgr:dword
extrn _gpLockShortDelay:dword ; Pointer to global constant 10 ms delay
if DBG
extrn _DbgPrint:proc
EXTRNP _HmgPrintBadHandle,2
endif
EXTRNP _KeDelayExecutionThread,3
EXTRNP HalRequestSoftwareInterrupt,1,IMPORT,FASTCALL
EXTRNP _PsGetCurrentProcessId,0
;------------------------------Public-Routine------------------------------;
; HmgInterlockedCompareAndSwap(pul,ulong0,ulong1)
;
; Compare *pul with ulong1, if equal then replace with ulong2 interlocked
;
; Returns:
; EAX = 1 if memory written, 0 if not
;
;--------------------------------------------------------------------------;
;
public @HmgInterlockedCompareAndSwap@12
@HmgInterlockedCompareAndSwap@12 proc near
mov eax,edx
mov edx,[esp]+4
.486
Lock1:
lock cmpxchg [ecx],edx
.386
jnz Return_Zero
mov eax,1
ret 4
Return_Zero:
xor eax,eax
ret 4
@HmgInterlockedCompareAndSwap@12 endp
;------------------------------Public-Routine------------------------------;
; HmgLock (hobj,objt)
;
; Lock a user object.
;
; Input:
; EAX -- scratch
; ECX -- hobj
; EDX -- objt
;
; Returns:
; EAX = pointer to locked object
;
; Error Return:
; EAX = 0, No error logged.
;
; History:
; 14-Jun-1995 -by- J. Andrew Goossen [andrewgo]
; Rewrote for Kernel Mode.
;
; 20-Dec-1993 -by- Patrick Haluptzok [patrickh]
; Move lock counts into object.
;
; 23-Sep-1993 -by- Michael Abrash [mikeab]
; Tuned ASM code.
;
; -Sep-1992 -by- David Cutler [DaveC]
; Write HmgAltLock, HmgAltCheckLock, and HmgObjtype in ASM.
;
; Thu 13-Aug-1992 13:21:47 -by- Charles Whitmer [chuckwh]
; Wrote it in ASM. The common case falls straight through.
;
; Wed 12-Aug-1992 17:38:27 -by- Charles Whitmer [chuckwh]
; Restructured the C code to minimize jumps.
;
; 29-Jun-1991 -by- Patrick Haluptzok patrickh
; Wrote it.
;--------------------------------------------------------------------------;
public @HmgLock@8
@HmgLock@8 proc near
push ebx ;Preserve register in call
if DBG
push ecx ;Stash hobj for debugging
push edx ;Stash objt for debugging
endif
push ecx ;Stash hobj for later
; KeEnterCriticalRegion
; KeGetCurrentThread()->KernelApcDisable -= 1;
mov ebx,fs:[PcPrcbData].PbCurrentThread ;ebx -> KeGetCurrentThread()
dec WORD PTR [ebx].ThKernelApcDisable
and ecx,INDEX_MASK
cmp ecx,_gcMaxHmgr
jae HmgLock_bad_handle_before_lock
shl ecx,4
.errnz size ENTRY - 16
add ecx,_gpentHmgr ;ecx -> Entry
HmgLock_resume::
; Perf: It would be nice if we could avoid these word size overrides,
; but unfortunately objectowner_Pid is currently a non-dword
; aligned offset.
mov ebx,[ecx].entry_ObjectOwner
stdCall _PsGetCurrentProcessId,<>
and eax,OBJECTOWNER_PID
and ebx,OBJECTOWNER_PID
cmp eax,ebx
jne HmgLock_check_for_public_owner
HmgLock_after_check_for_public_owner::
mov eax,[ecx].entry_ObjectOwner
mov ebx,[ecx].entry_ObjectOwner
and eax,NOT OBJECTOWNER_LOCK
or ebx,OBJECTOWNER_LOCK
.486
Lock4:
lock cmpxchg [ecx].entry_ObjectOwner,ebx
.386
mov ebx,eax ;Remember unlock value
jnz HmgLock_delay
; The handle is now locked
cmp dl,[ecx].entry_Objt
pop eax
jnz HmgLock_bad_handle_after_lock
; Perf: If FullUnique were kept on an odd word-boundary, we could
; avoid the shift word compare and instead do a 32 bit 'xor'
; and 'and':
shr eax,TYPE_SHIFT
cmp ax,[ecx].entry_FullUnique
jnz HmgLock_bad_handle_after_lock
mov eax,[ecx].entry_einfo
mov edx,fs:[PcPrcbData].PbCurrentThread ;edx ->KeGetCurrentThread()
cmp word ptr [eax].object_cExclusiveLock,0 ;Note, testing here...
;cExclusiveLock is a USHORT
jnz HmgLock_check_if_same_thread ;...and jumping here
mov byte ptr [eax].object_cExclusiveLock,1
;We can do a byte move
; because we know it was
; a zero word before
HmgLock_after_same_thread::
mov [eax].object_Tid,edx
mov [ecx].entry_ObjectOwner,ebx ;Unlock it
; eax is set to the proper return value
HmgLock_incAPC::
; KiLeaveCriticalRegion (eax must be preseerved)
;
; #define KiLeaveCriticalRegion() { \
; PKTHREAD Thread; \
; Thread = KeGetCurrentThread(); \
; if (((*((volatile ULONG *)&Thread->KernelApcDisable) += 1) == 0) && \
; (((volatile LIST_ENTRY *)&Thread->ApcState.ApcListHead[KernelMode])->Flink != \
; &Thread->ApcState.ApcListHead[KernelMode])) { \
; Thread->ApcState.KernelApcPending = TRUE; \
; KiRequestSoftwareInterrupt(APC_LEVEL); \
; } \
; }
;
mov ebx,fs:[PcPrcbData].PbCurrentThread ;eax -> KeGetCurrentThread()
inc WORD PTR [ebx].ThKernelApcDisable
jz HmgLock_LeaveCriticalRegion
HmgLock_Done::
if DBG
pop ebx ;Remove debug copy of objt
pop ebx ;Remove debug copy of hobj
endif
pop ebx
ret
; Roads less travelled...
HmgLock_check_for_public_owner:
test ebx,ebx
.errnz OBJECT_OWNER_PUBLIC
jz HmgLock_after_check_for_public_owner
HmgLock_bad_handle_before_lock::
pop ecx
jmp HmgLock_bad_handle
HmgLock_bad_handle_after_lock::
mov [ecx].entry_ObjectOwner,ebx ;Unlock it
HmgLock_bad_handle:
if DBG
; Retrieve the debug copies of 'hobj' and 'objt' from where they
; were pushed on the stack:
mov eax,[esp] ;objt
mov ecx,[esp+4] ;hobj
; Call a debug routine that prints a warning, complete with
; the name of the owning process, handle value, and expected type.
stdCall _HmgPrintBadHandle,<ecx,eax>
endif
xor eax,eax
jmp HmgLock_incAPC
HmgLock_check_if_same_thread::
inc dword ptr [eax].object_cExclusiveLock ; cExclusiveLock is USHORT
cmp edx,[eax].object_Tid ; but dword operation is faster on P5
je HmgLock_after_same_thread ; than a word operation
; Error case if already locked:
dec dword ptr [eax].object_cExclusiveLock ; same remark as for inc above
mov [ecx].entry_ObjectOwner,ebx ;Unlock it
if DBG
push offset HL_AlreadyLocked
call _DbgPrint
add esp,4
endif
jmp HmgLock_bad_handle
HmgLock_delay::
push ecx
push edx
mov eax,_gpLockShortDelay
stdCall _KeDelayExecutionThread,<KernelMode,0,eax>
pop edx
pop ecx
mov ebx,fs:[PcPrcbData].PbCurrentThread ;ebx -> KeGetCurrentThread()
jmp HmgLock_resume
HmgLock_LeaveCriticalRegion::
lea ecx,[ebx].ThApcState+AsApcListHead
mov edx,[ecx].LsFlink
cmp ecx,edx
jne HmgLock_CallInterrupt
if DBG
pop ebx ;Remove debug copy of objt
pop ebx ;Remove debug copy of hobj
endif
pop ebx
ret
HmgLock_CallInterrupt::
lea ecx,[ebx].ThApcState
mov BYTE PTR [ecx].AsKernelApcPending,1
push eax
mov ecx,APC_LEVEL
fstCall HalRequestSoftwareInterrupt
pop eax
jmp HmgLock_Done
@HmgLock@8 endp
;------------------------------Public-Routine------------------------------;
; HmgShareCheckLock (hobj,objt)
;
; Acquire a share lock on an object, PID owner must match current PID
; or be a public.
;
; Input:
; EAX -- scratch
; ECX -- hobj
; EDX -- objt
;
; Returns:
; EAX = pointer to referenced object
;
; Error Return:
; EAX = 0, No error logged.
;
;--------------------------------------------------------------------------;
public @HmgShareCheckLock@8
@HmgShareCheckLock@8 proc near
push ebx ;Preserve register in call
if DBG
push ecx ;Stash hobj for debugging
push edx ;Stash objt for debugging
endif
push ecx ;Stash hobj for later
; KeEnterCriticalRegion
; KeGetCurrentThread()->KernelApcDisable -= 1;
mov ebx,fs:[PcPrcbData].PbCurrentThread ;ebx -> KeGetCurrentThread()
dec WORD PTR [ebx].ThKernelApcDisable
and ecx,INDEX_MASK
cmp ecx,_gcMaxHmgr
jae HmgShareCheckLock_bad_handle_before_lock
shl ecx,4
.errnz size ENTRY - 16
add ecx,_gpentHmgr ;ecx -> Entry
HmgShareCheckLock_resume::
; Perf: It would be nice if we could avoid these word size overrides,
; but unfortunately objectowner_Pid is currently a non-dword
; aligned offset.
mov ebx,[ecx].entry_ObjectOwner
stdCall _PsGetCurrentProcessId,<>
and eax,OBJECTOWNER_PID
and ebx,OBJECTOWNER_PID
cmp eax,ebx
jne HmgShareCheckLock_check_for_public_owner
HmgShareCheckLock_after_check_for_public_owner::
mov eax,[ecx].entry_ObjectOwner
mov ebx,[ecx].entry_ObjectOwner
and eax,NOT OBJECTOWNER_LOCK
or ebx,OBJECTOWNER_LOCK
.486
Lock5:
lock cmpxchg [ecx].entry_ObjectOwner,ebx
.386
mov ebx,eax ;Remember unlock value
jnz HmgShareCheckLock_delay
; The handle is now locked
cmp dl,[ecx].entry_Objt
pop eax
jnz HmgShareCheckLock_bad_handle_after_lock
; Perf: If FullUnique were kept on an odd word-boundary, we could
; avoid the shift word compare and instead do a 32 bit 'xor'
; and 'and':
shr eax,TYPE_SHIFT
cmp ax,[ecx].entry_FullUnique
jnz HmgShareCheckLock_bad_handle_after_lock
mov eax,[ecx].entry_einfo ;Get pointer to object
if DBG
cmp [eax].object_ulShareCount, 0ffffffffH ;Check for overflow
jne HmgShareCheckLock_go
push offset HL_OverFlowShareRef
call _DbgPrint
add esp,4
int 3
HmgShareCheckLock_go:
endif
inc DWORD PTR [eax].object_ulShareCount
mov [ecx].entry_ObjectOwner,ebx ;Unlock it
HmgShareCheckLock_IncAPC::
; KiLeaveCriticalRegion (eax must be preseerved)
;
; #define KiLeaveCriticalRegion() { \
; PKTHREAD Thread; \
; Thread = KeGetCurrentThread(); \
; if (((*((volatile ULONG *)&Thread->KernelApcDisable) += 1) == 0) && \
; (((volatile LIST_ENTRY *)&Thread->ApcState.ApcListHead[KernelMode])->Flink != \
; &Thread->ApcState.ApcListHead[KernelMode])) { \
; Thread->ApcState.KernelApcPending = TRUE; \
; KiRequestSoftwareInterrupt(APC_LEVEL); \
; } \
; }
;
mov ebx,fs:[PcPrcbData].PbCurrentThread ;eax -> KeGetCurrentThread()
inc WORD PTR [ebx].ThKernelApcDisable
jz HmgShareCheckLock_LeaveCriticalRegion
; eax is set to the proper return value
HmgShareCheckLock_Done::
if DBG
pop ebx ;Remove debug copy of objt
pop ebx ;Remove debug copy of hobj
endif
pop ebx
ret
; Roads less travelled...
HmgShareCheckLock_check_for_public_owner:
test ebx,ebx
.errnz OBJECT_OWNER_PUBLIC
jz HmgShareCheckLock_after_check_for_public_owner
HmgShareCheckLock_bad_handle_before_lock::
pop ecx
jmp HmgShareCheckLock_bad_handle
HmgShareCheckLock_bad_handle_after_lock::
mov [ecx].entry_ObjectOwner,ebx ;Unlock it
HmgShareCheckLock_bad_handle::
if DBG
; Retrieve the debug copies of 'hobj' and 'objt' from where they
; were pushed on the stack:
mov eax,[esp] ;objt
mov ecx,[esp+4] ;hobj
; Call a debug routine that prints a warning, complete with
; the name of the owning process, handle value, and expected type.
stdCall _HmgPrintBadHandle,<ecx,eax>
endif
xor eax,eax
jmp HmgShareCheckLock_IncAPC
HmgShareCheckLock_delay::
push ecx
push edx
mov eax,_gpLockShortDelay
stdCall _KeDelayExecutionThread,<KernelMode,0,eax>
pop edx
pop ecx
mov ebx,fs:[PcPrcbData].PbCurrentThread ;ebx -> KeGetCurrentThread()
jmp HmgShareCheckLock_resume
HmgShareCheckLock_LeaveCriticalRegion::
lea ecx,[ebx].ThApcState+AsApcListHead
mov edx,[ecx].LsFlink
cmp ecx,edx
jne HmgShareCheckLock_CallInterrupt
if DBG
pop ebx ;Remove debug copy of objt
pop ebx ;Remove debug copy of hobj
endif
pop ebx
ret
HmgShareCheckLock_CallInterrupt::
lea ecx,[ebx].ThApcState
mov BYTE PTR [ecx].AsKernelApcPending,1
push eax
mov ecx,APC_LEVEL
fstCall HalRequestSoftwareInterrupt
pop eax
jmp HmgShareCheckLock_Done
@HmgShareCheckLock@8 endp
;------------------------------Public-Routine------------------------------;
; HmgShareLock (obj,objt)
;
;
; Acquire a share lock on an object, don't check PID owner
;
; Input:
; EAX -- scratch
; ECX -- hobj
; EDX -- objt
;
; Returns:
; EAX = pointer to referenced object
;
; Error Return:
; EAX = 0, No error logged.
;
;--------------------------------------------------------------------------;
public @HmgShareLock@8
@HmgShareLock@8 proc near
push ebx ;Preserve register in call
if DBG
push ecx ;Stash hobj for debugging
push edx ;Stash objt for debugging
endif
push ecx ;Stash hobj for later
; KeEnterCriticalRegion
; KeGetCurrentThread()->KernelApcDisable -= 1;
mov ebx,fs:[PcPrcbData].PbCurrentThread ;eax -> KeGetCurrentThread()
dec WORD PTR [ebx].ThKernelApcDisable
and ecx,INDEX_MASK
cmp ecx,_gcMaxHmgr
jae HmgShareLock_bad_handle_before_lock
shl ecx,4
.errnz size ENTRY - 16
add ecx,_gpentHmgr ;ecx -> Entry
HmgShareLock_resume::
mov eax,[ecx].entry_ObjectOwner
mov ebx,[ecx].entry_ObjectOwner
and eax,NOT OBJECTOWNER_LOCK
or ebx,OBJECTOWNER_LOCK
.486
Lock6:
lock cmpxchg [ecx].entry_ObjectOwner,ebx
.386
mov ebx,eax ;Remember unlock value
jnz HmgShareLock_delay
; The handle is now locked
cmp dl,[ecx].entry_Objt
pop eax
jnz HmgShareLock_bad_handle_after_lock
; Perf: If FullUnique were kept on an odd word-boundary, we could
; avoid the shift word compare and instead do a 32 bit 'xor'
; and 'and':
shr eax,TYPE_SHIFT
cmp ax,[ecx].entry_FullUnique
jnz HmgShareLock_bad_handle_after_lock
mov eax,[ecx].entry_einfo ;Get pointer to object
if DBG
cmp [eax].object_ulShareCount, 0ffffffffH ;Check for overflow
jne HmgShareLock_go
push offset HL_OverFlowShareRef
call _DbgPrint
add esp,4
int 3
HmgShareLock_go:
endif
inc DWORD PTR [eax].object_ulShareCount
mov [ecx].entry_ObjectOwner,ebx ;Unlock it
HmgShareLock_incAPC::
; KiLeaveCriticalRegion (eax must be preseerved)
;
; #define KiLeaveCriticalRegion() { \
; PKTHREAD Thread; \
; Thread = KeGetCurrentThread(); \
; if (((*((volatile ULONG *)&Thread->KernelApcDisable) += 1) == 0) && \
; (((volatile LIST_ENTRY *)&Thread->ApcState.ApcListHead[KernelMode])->Flink != \
; &Thread->ApcState.ApcListHead[KernelMode])) { \
; Thread->ApcState.KernelApcPending = TRUE; \
; KiRequestSoftwareInterrupt(APC_LEVEL); \
; } \
; }
;
mov ebx,fs:[PcPrcbData].PbCurrentThread ;ebx -> KeGetCurrentThread()
inc WORD PTR [ebx].ThKernelApcDisable
jz HmgShareLock_LeaveCriticalRegion
HmgShareLock_Done::
; eax is set to the proper return value
if DBG
pop ebx ;Remove debug copy of objt
pop ebx ;Remove debug copy of hobj
endif
pop ebx
ret
; Roads less travelled...
HmgShareLock_bad_handle_before_lock::
pop ecx
jmp HmgShareLock_bad_handle
HmgShareLock_bad_handle_after_lock::
mov [ecx].entry_ObjectOwner,ebx ;Unlock it
HmgShareLock_bad_handle::
if DBG
; Retrieve the debug copies of 'hobj' and 'objt' from where they
; were pushed on the stack:
mov eax,[esp] ;objt
mov ecx,[esp+4] ;hobj
; Call a debug routine that prints a warning, complete with
; the name of the owning process, handle value, and expected type.
stdCall _HmgPrintBadHandle,<ecx,eax>
endif
xor eax,eax
jmp HmgShareLock_incAPC
HmgShareLock_delay::
push ecx
push edx
mov eax,_gpLockShortDelay
stdCall _KeDelayExecutionThread,<KernelMode,0,eax>
pop edx
pop ecx
jmp HmgShareLock_resume
HmgShareLock_LeaveCriticalRegion::
lea ecx,[ebx].ThApcState+AsApcListHead
mov edx,[ecx].LsFlink
cmp ecx,edx
jne HmgShareLock_CallInterrupt
if DBG
pop ebx ;Remove debug copy of objt
pop ebx ;Remove debug copy of hobj
endif
pop ebx
ret
HmgShareLock_CallInterrupt::
lea ecx,[ebx].ThApcState
mov BYTE PTR [ecx].AsKernelApcPending,1
push eax
mov ecx,APC_LEVEL
fstCall HalRequestSoftwareInterrupt
pop eax
jmp HmgShareLock_Done
@HmgShareLock@8 endp
;------------------------------Public-Routine------------------------------;
; HmgIncrementShareReferenceCount (pobj)
;
;
; Increment shared reference count, no checking
;
; Input:
; EAX -- scratch
; ECX -- pobj
;
; Returns:
; EAX = pointer to referenced object
;
; Error Return:
; EAX = 0, No error logged.
;
;--------------------------------------------------------------------------;
public @HmgIncrementShareReferenceCount@4
@HmgIncrementShareReferenceCount@4 proc near
push ebx ;Preserve register in call
push ecx ;Stash pobj for later
; KeEnterCriticalRegion
; KeGetCurrentThread()->KernelApcDisable -= 1;
mov ebx,fs:[PcPrcbData].PbCurrentThread ;eax -> KeGetCurrentThread()
dec WORD PTR [ebx].ThKernelApcDisable
mov ecx, [ecx]
and ecx,INDEX_MASK
shl ecx,4
.errnz size ENTRY - 16
add ecx,_gpentHmgr ;ecx -> Entry
HmgIncrementShareReferenceCount_resume::
mov eax,[ecx].entry_ObjectOwner
mov ebx,[ecx].entry_ObjectOwner
and eax,NOT OBJECTOWNER_LOCK
or ebx,OBJECTOWNER_LOCK
.486
Lock7:
lock cmpxchg [ecx].entry_ObjectOwner,ebx
.386
mov ebx,eax ;Remember unlock value
jnz HmgIncrementShareReferenceCount_delay
; The handle is now locked
mov eax,[ecx].entry_einfo ;Get pointer to object
inc DWORD PTR [eax].object_ulShareCount
mov [ecx].entry_ObjectOwner,ebx ;Unlock it
HmgIncrementShareReferenceCount_incAPC::
; KiLeaveCriticalRegion (eax must be preseerved)
;
; #define KiLeaveCriticalRegion() { \
; PKTHREAD Thread; \
; Thread = KeGetCurrentThread(); \
; if (((*((volatile ULONG *)&Thread->KernelApcDisable) += 1) == 0) && \
; (((volatile LIST_ENTRY *)&Thread->ApcState.ApcListHead[KernelMode])->Flink != \
; &Thread->ApcState.ApcListHead[KernelMode])) { \
; Thread->ApcState.KernelApcPending = TRUE; \
; KiRequestSoftwareInterrupt(APC_LEVEL); \
; } \
; }
;
mov ebx,fs:[PcPrcbData].PbCurrentThread ;ebx -> KeGetCurrentThread()
inc WORD PTR [ebx].ThKernelApcDisable
jz HmgIncrementShareReferenceCount_LeaveCriticalRegion
HmgIncrementShareReferenceCount_Done::
; eax is set to the proper return value
pop ecx
pop ebx
ret
; Roads less travelled...
HmgIncrementShareReferenceCount_delay::
push ecx
mov eax,_gpLockShortDelay
stdCall _KeDelayExecutionThread,<KernelMode,0,eax>
pop ecx
jmp HmgIncrementShareReferenceCount_resume
HmgIncrementShareReferenceCount_LeaveCriticalRegion::
lea ecx,[ebx].ThApcState+AsApcListHead
mov edx,[ecx].LsFlink
cmp ecx,edx
jne HmgIncrementShareReferenceCount_CallInterrupt
pop ecx
pop ebx
ret
HmgIncrementShareReferenceCount_CallInterrupt::
lea ecx,[ebx].ThApcState
mov BYTE PTR [ecx].AsKernelApcPending,1
push eax
mov ecx,APC_LEVEL
fstCall HalRequestSoftwareInterrupt
pop eax
jmp HmgIncrementShareReferenceCount_Done
@HmgIncrementShareReferenceCount@4 endp
;------------------------------Public-Routine------------------------------;
; HmgDecrementShareReferenceCount (pobj)
;
;
; Decrement shared reference count, no checking
;
; Input:
; EAX -- scratch
; ECX -- pobj
;
; Returns:
;
; Error Return:
; EAX = 0, No error logged.
;
;--------------------------------------------------------------------------;
public @HmgDecrementShareReferenceCount@4
@HmgDecrementShareReferenceCount@4 proc near
push ebx ;Preserve register in call
push ecx ;Stash pobj for later
; KeEnterCriticalRegion
; KeGetCurrentThread()->KernelApcDisable -= 1;
mov ebx,fs:[PcPrcbData].PbCurrentThread ;eax -> KeGetCurrentThread()
dec WORD PTR [ebx].ThKernelApcDisable
mov ecx, [ecx]
and ecx,INDEX_MASK
shl ecx,4
.errnz size ENTRY - 16
add ecx,_gpentHmgr ;ecx -> Entry
HmgDecrementShareReferenceCount_resume::
mov eax,[ecx].entry_ObjectOwner
mov ebx,[ecx].entry_ObjectOwner
and eax,NOT OBJECTOWNER_LOCK
or ebx,OBJECTOWNER_LOCK
.486
Lock8:
lock cmpxchg [ecx].entry_ObjectOwner,ebx
.386
mov ebx,eax ;Remember unlock value
jnz HmgDecrementShareReferenceCount_delay
; The handle is now locked
mov edx,[ecx].entry_einfo ;Get pointer to object
mov eax, [edx].object_ulShareCount
dec DWORD PTR [edx].object_ulShareCount
mov [ecx].entry_ObjectOwner,ebx ;Unlock it
HmgDecrementShareReferenceCount_incAPC::
; KiLeaveCriticalRegion (eax must be preseerved)
;
; #define KiLeaveCriticalRegion() { \
; PKTHREAD Thread; \
; Thread = KeGetCurrentThread(); \
; if (((*((volatile ULONG *)&Thread->KernelApcDisable) += 1) == 0) && \
; (((volatile LIST_ENTRY *)&Thread->ApcState.ApcListHead[KernelMode])->Flink != \
; &Thread->ApcState.ApcListHead[KernelMode])) { \
; Thread->ApcState.KernelApcPending = TRUE; \
; KiRequestSoftwareInterrupt(APC_LEVEL); \
; } \
; }
;
mov ebx,fs:[PcPrcbData].PbCurrentThread ;ebx -> KeGetCurrentThread()
inc WORD PTR [ebx].ThKernelApcDisable
jz HmgDecrementShareReferenceCount_LeaveCriticalRegion
HmgDecrementShareReferenceCount_Done::
; eax is set to the proper return value
pop ecx
pop ebx
ret
; Roads less travelled...
HmgDecrementShareReferenceCount_delay::
push ecx
mov eax,_gpLockShortDelay
stdCall _KeDelayExecutionThread,<KernelMode,0,eax>
pop ecx
jmp HmgDecrementShareReferenceCount_resume
HmgDecrementShareReferenceCount_LeaveCriticalRegion::
lea ecx,[ebx].ThApcState+AsApcListHead
mov edx,[ecx].LsFlink
cmp ecx,edx
jne HmgDecrementShareReferenceCount_CallInterrupt
pop ecx
pop ebx
ret
HmgDecrementShareReferenceCount_CallInterrupt::
lea ecx,[ebx].ThApcState
mov BYTE PTR [ecx].AsKernelApcPending,1
push eax
mov ecx,APC_LEVEL
fstCall HalRequestSoftwareInterrupt
pop eax
jmp HmgDecrementShareReferenceCount_Done
@HmgDecrementShareReferenceCount@4 endp
_TEXT ends
endif
end