210 lines
7.6 KiB
NASM
210 lines
7.6 KiB
NASM
|
;***************************************************************************
|
||
|
;* 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
|
||
|
|