windows-nt/Source/XPSP1/NT/base/mvdm/wow16/toolhelp/usergdi2.asm

210 lines
7.6 KiB
NASM
Raw Normal View History

2020-09-26 03:20:57 -05:00
;***************************************************************************
;* USERGDI2.ASM
;*
;* Assembly routines used in computing heap space remaining for
;* USER, GDI, and any other heaps.
;*
;***************************************************************************
INCLUDE TOOLPRIV.INC
SWAPPRO = 0
PMODE32 = 0
PMODE = 1
INCLUDE WINKERN.INC
INCLUDE NEWEXE.INC
;** This slimy thing is from GDIOBJ.INC and is subtracted from the
;** object type nunbers only in 3.1
LT_GDI_BASE EQU ('G' or ('O' * 256)) - 1
;** External functions
externNP HelperVerifyLocHeap
externNP HelperHandleToSel
;** Functions
sBegin CODE
assumes CS,CODE
assumes DS,DATA
.286p
; UserGdiDGROUP
; Returns a handle to the DGROUP segment for a given module
;
; HANDLE UserGdiDGROUP(
; HANDLE hModule)
cProc UserGdiDGROUP, <PUBLIC,NEAR>, <di,si>
parmW hModule
cBegin
mov ax,hModule ;Get the handle
cCall HelperHandleToSel, <ax> ;Convert to a selector
mov es,ax ;Point with ES for this
xor ax,ax ;Prepare to return NULL
cmp es:[ne_magic],NEMAGIC ;Make sure we have a module database
jnz UGD_End ;It isn't so get out
mov bx,es:[ne_pautodata] ;Point to the segment table entry
mov ax,es:[bx].ns_handle ;Get the handle from the table
cCall HelperHandleToSel, <ax> ;Convert to a selector for return
UGD_End:
cEnd
; UserGdiSpace
; This function was stolen from KERNEL where it is used to compute
; the space remaining in the USER and GDI heaps. It actually works
; on any local heap.
;
; DWORD UserGdiSpace(
; HANDLE hData)
; HIWORD of return is maximum size of heap (64K less statics, etc.)
; LOWORD of return is space remaining on heap
cProc UserGdiSpace, <PUBLIC,NEAR>, <di,si,ds>
parmW hData
cBegin
;** Count the free space in this heap. First: Is this heap valid?
mov ax,hData ;Get the heap selector
cCall HelperVerifyLocHeap ;Call the verify routine
mov ax,0 ;In case we jump -- set error
mov dx,0 ; Use MOV to not mess up carry
jc UGS_Exit ;No valid local heap!!
;** Loop through all local blocks, adding free space
cCall HelperHandleToSel, <hData> ;Convert to selector
mov ds,ax ;Point to the segment
mov di,ds:[6] ;Get pHeapInfo
mov di,[di].hi_first ;First arena header
mov di,[di].la_free_next ;First free block
UGS_Loop:
add ax,[di].la_size ;Add in size of this block
sub ax,SIZE LocalArenaFree ;Less block overhead
mov si,[di].la_free_next ;Get next free block
or si,si ;NULL?
jz UGS_Break ;Yes, say we're done
cmp si,di ;Last block? (points to self)
mov di,si ;Save for next time around
jnz UGS_Loop ;Not last block so loop some more
UGS_Break:
;** We have the size of the local heap
mov si,ax ;Save the size
mov cx,ds ;Get the selector in a non-segreg
lsl ax,cx ;Get the size of the segment
neg ax ;64K - segment size
add ax,si ;Add in the free holes in the heap
mov dx,-1 ;Compute the max size of heap
sub dx,ds:[6] ; which is 64K less statics
UGS_Exit:
cEnd
; UserGdiType
;
; Tries to compute the type of local heap block if possible
; Prototype:
;
; void PASCAL UserGdiType(
; LOCALENTRY FAR *lpLocal)
cProc UserGdiType, <PUBLIC,NEAR>, <si,di>
parmD lpLocal
cBegin
;** Get info from our static variables
mov ax,_DATA ;Get the variables first
mov ds,ax ;Point to our DS
mov bx,hUserHeap ;BX=User's heap block
mov cx,hGDIHeap ;CX=GDI's heap block
;** See if we can do anything with this heap
les si,lpLocal ;Get a pointer to the structure
mov es:[si].le_wType,LT_NORMAL ;In case we don't find anything
mov ax,es:[si].le_hHeap ;Get the heap pointer
cmp ax,bx ;User's heap?
jnz UGT_10 ;Nope, try next
cCall GetUserType ;Call routine to get user type
jmp SHORT UGT_End ;Get out
UGT_10: cmp ax,cx ;GDI's heap?
jnz UGT_End ;Nope, can't do anything with it
cCall GetGDIType ;Call routine to get GDI type
UGT_End:
cEnd
;** Internal helper functions
; GetUserType
;
; Uses the tags in debug USER.EXE to give information on what type
; block is pointed to by the current LOCALENTRY structure.
; Caller: ES:SI points to the parameter LOCALENTRY structure
; Return: LOCALENTRY structure is correctly updated
cProc GetUserType, <NEAR>
cBegin
;** Make sure we have a function to call
cmp WORD PTR lpfnGetUserLocalObjType + 2,0 ;Selector zero?
je GUT_End ;Yes
;** Call USER to get the type
push es ;Save ES
mov bx,es:[si].le_wAddress ;Get the block address
sub bx, la_fixedsize ;The USER call needs the arena header
test es:[si].le_wFlags, LF_MOVEABLE ;Moveable block?
jz @F ;No
sub bx, (SIZE LocalArena) - la_fixedsize ;Moveable arena bigger
@@: push bx ;Parameter arena handle
call DWORD PTR lpfnGetUserLocalObjType ;Call the function
pop es
xor ah,ah ;Clear the upper byte
mov es:[si].le_wType,ax ;Save the type
GUT_End:
cEnd
; GetGDIType
;
; Uses the tags in debug GDI.EXE to give information on what type
; block is pointed to by the current LOCALENTRY structure.
; Caller: ES:SI points to the parameter LOCALENTRY structure
; Return: LOCALENTRY structure is correctly updated
cProc GetGDIType, <NEAR>, <ds>
cBegin
;** All fixed blocks are unknown to us
test es:[si].le_wFlags,LF_FIXED ;Is it fixed?
jz GGT_10 ;Nope
jmp SHORT GGT_End ;Yes, get out
GGT_10:
;** Prepare to find the type
cCall HelperHandleToSel,es:[si].le_hHeap ;Get the selector value
mov cx,wTHFlags ;Save for when we trash DS
mov ds,ax ;Get the heap pointer
mov di,es:[si].le_wAddress ;Get the block pointer
;** Get the type word
mov ax,[di+2] ;Get the type word from the heap
and ax,05fffh ;Mask out the stock object flag
test cx,TH_WIN30 ;In 3.0?
jnz CGT_Win30 ;Yes
sub ax,LT_GDI_BASE ;No, subtract type tag base
CGT_Win30:
cmp ax,LT_GDI_MAX ;Recognizable type code?
ja GGT_End ;No, get out
mov es:[si].le_wType,ax ;Save in the structure
GGT_End:
cEnd
sEnd
END