2025-04-27 07:49:33 -04:00

924 lines
30 KiB
NASM
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 DWORD 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 DWORD 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 DWORD 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 DWORD 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 DWORD 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 DWORD 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 DWORD 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 DWORD 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 DWORD 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 DWORD 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