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.
 
 
 
 
 
 

2266 lines
80 KiB

TITLE GINTERF - Global Memory Manager interface procedures
.xlist
include kernel.inc
include pdb.inc
include tdb.inc
include newexe.inc
ifdef WOW
include wow.inc
include wowkrn.inc
include vint.inc
include wowcmpat.inc
GMEMSTATUS_block STRUC
dwLength dd ? ;/* size in bytes of MEMORYSTATUS structure */
dwMemoryLoad dd ? ;/* percent of memory being used */
dwTotalPhys dd ? ;/* total bytes of physical memory */
dwAvailPhys dd ? ;/* unallocated bytes of physical memory */
dwTotalPageFile dd ? ;/* total bytes of paging file */
dwAvailPageFile dd ? ;/* unallocated bytes of paging file */
dwTotalVirtual dd ? ;/* total user bytes of virtual address space */
dwAvailVirtual dd ? ;/* unallocated user bytes of virtual address space */
GMEMSTATUS_block ENDS
endif
.list
.386p
include protect.inc
CheckHeap MACRO name
local a
if KDEBUG
extrn CheckGlobalHeap :near
call CheckGlobalHeap
jnc short a
or ax,ERR_GMEM
xor bx,bx
kerror <>,<&name: Invalid global heap>,dx,bx
a:
endif
endm
ifdef WOW
externFP WowCursorIconOp
externFP GlobalMemoryStatus
externFP WowDdeFreeHandle
externFP FindAndReleaseDib
externNP MyGetAppWOWCompatFlags
endif
externW pStackTop
externW pStackMin
externW pStackBot
DataBegin
externB Kernel_Flags
externB fBooting
externW hGlobalHeap
externW pGlobalHeap
externW curTDB
externW loadTDB
externW hExeHead
externW WinFlags
GSS_SI dw 0
GSS_DS dw 0
GSS_RET dd 0
DataEnd
sBegin CODE
assumes CS,CODE
if SDEBUG
externNP DebugFreeSegment
endif
externNP galloc
externNP grealloc
externNP gfree
externNP glock
externNP gunlock
externNP gfreeall
externNP galign
externNP gcompact
externNP gmovebusy
externNP gsearch
externNP genter
externNP gleave
externNP gavail
externNP glrutop
externNP glrubot
externNP glrudel
externNP glruadd
externNP gmarkfree
externNP ShrinkHeap
externNP HackCheck
externNP get_arena_pointer32
externNP get_physical_address
externNP pdref
externNP alloc_arena_header
externNP free_arena_header
externNP PreAllocArena
externNP MyGetAppCompatFlags
externNP DPMIProc
externW gdtdsc
if KDEBUG
externFP OutputDebugString
ThisIsForTurboPascal:
db "A program has attempted an invalid selector-to-handle conversion.",13,10,"Attempting to correct this error.",13,10,0
endif
if KDEBUG
ifndef WOW
externNP xhandle_norip
endif
ifdef ?CHECKMEM
cProc CheckMem,<PUBLIC,NEAR>
cBegin nogen
or ax,ax
jnz short cm_okay
cmp [di].hi_check,di
je short cm_okay
kerror ERR_GMEM,<GlobalAlloc or ReAlloc failed>,di,cx
xor ax,ax
xor cx,cx
xor dx,dx
cm_okay:
ret
cEnd nogen
endif
endif
cProc GetDefOwner,<PUBLIC,NEAR>
cBegin nogen
CheckKernelDS fs
ReSetKernelDS fs
mov cx,curTDB
jcxz xxxx
mov es,cx
mov cx,loadTDB
jcxz xxx
mov es,cx
xxx: mov cx,es:[TDB_PDB]
inc cx
xxxx: dec cx
ret
UnSetKernelDS fs
cEnd nogen
;-----------------------------------------------------------------------;
; gbtop ;
; ;
; Converts a 32-bit byte count to a 16-bit paragraph count. ;
; ;
; Arguments: ;
; AX = allocation flags or -1 if called from GlobalCompact ;
; BX = stack address of 32-bit unsigned integer ;
; DX = handle being reallocated or zero ;
; DS:DI = address of GlobalInfo for global heap ;
; ;
; Returns: ;
; AX = updated allocation flags ;
; EBX = #bytes needed to contain that many bytes ;
; CX = owner value to use ;
; DX = handle being reallocated or zero ;
; ;
; Error Returns: ;
; ;
; Registers Preserved: ;
; ;
; Registers Destroyed: ;
; ;
; Calls: ;
; ;
; History: ;
; ;
; Wed Dec 03, 1986 10:20:01p -by- David N. Weise [davidw] ;
; Added this nifty comment block. ;
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc gbtop,<PUBLIC,NEAR>
cBegin nogen
CheckKernelDS fs
ReSetKernelDS fs
mov ebx, dword ptr ss:[bx]
add ebx, 15
jc short gbtop1
and bl, not 15 ; Round to 16 byte boundary
cmp ebx, (16*1020*1024) ; Too big?
jbe short gbtop2 ; no.
gbtop1:
mov ebx, 07FFFFFFFh ; Make it a ridiculous value
gbtop2:
inc ax
jnz short gbtop2a
jmp gbtopx ; All done if called from GlobalCompact
gbtop2a:
dec ax
mov cx, [bp].savedCS
push eax
cCall get_arena_pointer32,<cx>
mov esi,eax
pop eax
mov cx,hExeHead ; CX = KERNEL exe header
cmp fBooting,0 ; Done booting?
jne short gbtop3 ; No, must be KERNEL allocating then
cmp cx,ds:[esi].pga_owner ; Is the KERNEL calling us?
je short gbtop3 ; Yes, let him party
and ax,not GA_INTFLAGS ; No, then cant use these flags
and al, NOT GA_ALLOCHIGH
mov es,ds:[esi].pga_owner ; ES -> module database
cmp es:[di].ne_magic,NEMAGIC; Valid?
jne short gbtop2b ; No
test es:[di].ne_flags,NENOTP ; Yes, is it an app?
jnz short gbtop3 ; No, don't force it moveable
gbtop2b:
or al, GA_MOVEABLE ; Force it moveable
gbtop3:
mov cl,GA_SEGTYPE ; Isolate segment type bits in CL
and cl,al
mov [di].gi_cmpflags,al ; Save flags for gcompact
and [di].gi_cmpflags,CMP_FLAGS
or [di].gi_cmpflags, COMPACT_ALLOC ; Not a call from GlobalCompact
or dx, dx ; ReAllocating?
jnz short gbtop4 ; Yes, allow low
test al,GA_MOVEABLE ; Is this a moveable request?
jz short gbtop4 ; No, then go allocate low
test cl,GA_DISCCODE ; Yes, is this discardable code?
jz short gbtop4 ; Yes, then allocate high
or al,GA_ALLOCHIGH ; No, then allocate low
or [di].gi_cmpflags,GA_ALLOCHIGH
gbtop4:
push ax ; Under Win1.0x ANY bit in 0Fh meant
mov al,HE_DISCARDABLE ; make discardable.
and ah,al ; Under Win2.0x ONLY 01h or 0Fh means
cmp ah,al ; discardable.
pop ax
jnz short gbtop4a
and ah,not HE_DISCARDABLE ; Yes, convert to boolean value
or ah,GA_DISCARDABLE
gbtop4a:
gbtop4b:
and ah,NOT GA_SEGTYPE ; Clear any bogus flags
or ah,cl ; Copy segment type bits
test ah,GA_SHAREABLE ; Shared memory request?
jz GetDefOwner ; No, default action
mov cx,[bp].savedCS ; Yes, make owner same as
push eax
cCall get_arena_pointer32,<cx>
cmp esi,eax
je short @F
int 3
@@:
pop eax
mov cx,ds:[esi].pga_owner ; owner of calling code segment
gbtopx:
ret
UnSetKernelDS fs
cEnd nogen
; The remainder of this file implements the exported interface to the
; global memory manager. A summary follows:
; HANDLE far PASCAL GlobalAlloc( WORD, DWORD );
; HANDLE far PASCAL GlobalReAlloc( HANDLE, DWORD, WORD );
; HANDLE far PASCAL GlobalFree( HANDLE );
; HANDLE far PASCAL GlobalFreeAll( WORD );
; char far * far PASCAL GlobalLock( HANDLE );
; BOOL far PASCAL GlobalUnlock( HANDLE );
; DWORD far PASCAL GlobalSize( HANDLE );
; DWORD far PASCAL GlobalCompact( DWORD );
; #define GlobalDiscard( h ) GlobalReAlloc( h, 0L, GMEM_MOVEABLE )
; HANDLE far PASCAL GlobalHandle( WORD );
; HANDLE far PASCAL LockSegment( WORD );
; HANDLE far PASCAL UnlockSegment( WORD );
cProc IGlobalAlloc,<PUBLIC,FAR>
parmW flags
parmD nbytes
cBegin
GENTER32 ; About to modify memory arena
cCall MyGetAppCompatFlags ; Ignore the NODISCARD flag
test al, GACF_IGNORENODISCARD ; for selected modules
mov ax, flags
jz short @f
call IsKernelCalling ; needs caller's CS @ [bp+4]
jz short @f ; skip hack if kernel calling us
and al, NOT GA_NODISCARD
@@:
xor dx,dx ; No handle
lea bx,nbytes ; Convert requested bytes to paragraphs
call gbtop ; ... into BX
call galloc
ifdef ?CHECKMEM
if KDEBUG
call CheckMem
endif
endif
CheckHeap GlobalAlloc
GLEAVE32
if kdebug
or ax, ax
jnz @F
push ax
push bx
mov bx, seg_nbytes
mov ax, off_nbytes
krDebugOut <DEB_TRACE or DEB_krMemMan>, "GlobalAlloc(#bx#AX) failed for %ss2"
pop bx
pop ax
@@:
endif
cEnd
cProc IGlobalReAlloc,<PUBLIC,FAR>
parmW handle
parmD nbytes
parmW rflags
cBegin
;
; Does this thing have any ring bits or LDT bit? If not, then it
; could be a selector incorrectly converted to a handle.
;
test byte ptr handle,7
jnz SHORT @F
if KDEBUG
Trace_Out "GlobalReAlloc:"
push seg ThisIsForTurboPascal
push offset ThisIsForTurboPascal
cCall OutputDebugString
int 3
endif
dec handle
@@:
GENTER32 ; About to modify memory arena
cCall MyGetAppCompatFlags ; Ignore the NODISCARD flag
test al, GACF_IGNORENODISCARD ; for selected modules
mov ax, rflags
jz short @f
call IsKernelCalling ; needs caller's CS @ [bp+4]
jz short @f ; skip hack if kernel calling us
and al, NOT GA_NODISCARD
@@:
#ifdef WOW
push ax
; check for suspicious dib memory
mov dx, handle
call pdref
; check if the obj is locked
or ch,ch
jz short gr_proceed
; here, check for phantom flag... this might mean
; it's dib sec
test cl, GAH_PHANTOM
jz short gr_proceed
; if we are here - mem object is locked and boogie flag is set
; sufficient reason to check with wow32 to see if this is
; pesky dib section
cCall FindAndReleaseDib, <handle, FUN_GLOBALREALLOC>
gr_proceed:
pop ax
#endif
mov dx,handle
; mov ax,rflags
lea bx,nbytes ; Convert requested bytes to paragraphs
call gbtop ; ... into BX
call grealloc
gr_done:
CheckHeap GlobalReAlloc
GLEAVE32
cEnd
cProc DiscardTheWorld,<PUBLIC,NEAR>
cBegin
GENTER32
mov [di].gi_cmpflags, GA_DISCCODE+COMPACT_ALLOC
mov edx, -1
call gcompact
GLEAVE32
cEnd
; Returns with Z flag set if ss:[bp+4] is a kernel code segment selector.
; Uses: DX, flags.
cProc IsKernelCalling,<PUBLIC,NEAR>
cBegin nogen
mov dx, [bp+4] ; CS of GlobalAlloc caller
cmp dx, IGROUP
jz @f
cmp dx, _NRESTEXT
jz @f
cmp dx, _MISCTEXT
@@:
ret
cEnd nogen
;-----------------------------------------------------------------------;
; GlobalFree ;
; ;
; Frees the given object. If the object lives in someone elses banks ;
; then the argument MUST be a handle entry. ;
; ;
; Arguments: ;
; parmW handle ;
; ;
; Returns: ;
; ;
; Error Returns: ;
; ;
; Registers Preserved: ;
; ;
; Registers Destroyed: ;
; ;
; Calls: ;
; ;
; History: ;
; ;
; Wed 26-Apr-1989 15:33:18 -by- David N. Weise [davidw] ;
; Added the zero'ing of ES on exit. ;
; ;
; Sat Apr 25, 1987 10:23:13p -by- David N. Weise [davidw] ;
; Added support for EMS and added this nifty comment block. ;
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc IGlobalFree,<PUBLIC,FAR>
parmW handle
ifdef WOW
DsOnStack equ [bp][-2]
endif
; if you add any local params or make this nogen or something similar,
; the references to [bp][-2] to access DS on stack will need to change!
cBegin
GENTER32 ; About to modify memory arena
mov es, di ; We may be freeing what is in ES
xor ax,ax ; In case handle = 0.
mov dx,handle
or dx,dx
jnz @F
jmp nothing_to_free
@@:
;
; Does this thing have any ring bits or LDT bit? If not, then it
; could be a selector incorrectly converted to a handle.
;
test dl,7
jnz SHORT @F
if KDEBUG
Trace_Out "GlobalFree:"
push seg ThisIsForTurboPascal
push offset ThisIsForTurboPascal
cCall OutputDebugString
int 3
endif
dec dx
@@:
push dx
call pdref ; returns dx=handle, ax=selector
pushf ; save pdref Z flag return
ifdef WOW
;
; [bp][-2] has been changed to DsOnStack
;
endif
cmp ax,DsOnStack ; Are we about to free the DS on
jz short yup ; the stack and GP?
cmp dx,DsOnStack
jnz short nope
yup: xor dx,dx ; Yup, zero DS image on stack...
mov DsOnStack,dx
nope:
popf ; flags from pdref, Z set if discarded
pop dx
jz @f ; discarded can be freed, but has
; no arena pointer
or esi, esi ; Handle invalid if arena ptr = 0
jz nothing_to_free
@@:
ifdef WOW
or ch,ch
jz short gf_checkgicon
; here, check for phantom flag...
test cl, GAH_PHANTOM
jz gf_checkgicon
; sufficient reason to check with wow32 to see if this is
; pesky dib section
push dx ; dx is the only one that needs saving
cCall FindAndReleaseDib, <dx, FUN_GLOBALFREE>
or ax, ax ; if true, then just bail out, else free...
pop dx
jz gf_checkgicon
; now call the pdref again... as dx is set to selector
call pdref ; ret handle - also ok
jmps gf_notdib ; not a dib anymore...
gf_checkgicon:
endif
if KDEBUG
test dl, GA_FIXED
jnz short freeo
or ch,ch ; Debugging check for count underflow
jz short freeo
pushad
xor bx,bx
kerror ERR_GMEMUNLOCK,<GlobalFree: freeing locked object>,bx,handle
popad
freeo:
endif
ifdef WOW
test cl, GAH_CURSORICON ; call to pdref above sets cl
; Note: GAH_CURSORICON is also used for Free'ing
; Accelerators - a-craigj
jz gf_wowdde
push ax ; save
push bx
push dx
push es
push fs ; fs needs saving
push handle
push FUN_GLOBALFREE
call WowCursorIconOp
or ax, ax ; if TRUE 'free' else 'dont free, fake success'
pop fs
pop es
pop dx
pop bx
pop ax ; restore
jnz gf_notglobalicon
xor ax, ax ; fake success
xor cx, cx
jmps nothing_to_free
gf_wowdde:
test cl, GAH_WOWDDEFREEHANDLE
jz gf_noticon
push ax
push bx
push dx
push es ; save these
push fs
push handle
call WowDdeFreeHandle
or ax, ax ; if TRUE 'free' else 'dont free, fake success'
pop fs
pop es
pop dx
pop bx
pop ax
jnz gf_notglobalicon
xor ax, ax ; fake success
xor cx, cx
jmps nothing_to_free
gf_notdib:
gf_notglobalicon:
gf_noticon:
endif
xor cx,cx ; Dont check owner field
call gfree
nothing_to_free:
CheckHeap GlobalFree
GLEAVE32
cEnd
;-----------------------------------------------------------------------;
; GlobalFreeAll ;
; ;
; Frees all of the global objects belonging to the given owner. ;
; ;
; Arguments: ;
; parmW id ;
; ;
; Returns: ;
; ;
; Error Returns: ;
; ;
; Registers Preserved: ;
; ;
; Registers Destroyed: ;
; ;
; Calls: ;
; ;
; History: ;
; ;
; Wed 26-Apr-1989 15:33:18 -by- David N. Weise [davidw] ;
; Added the zero'ing of ES on exit. ;
; ;
; Sat Apr 25, 1987 10:23:13p -by- David N. Weise [davidw] ;
; Added support for EMS and added this nifty comment block. ;
;-----------------------------------------------------------------------;
cProc GlobalFreeAll,<PUBLIC,FAR>
parmW id
cBegin
GENTER32 ; About to modify memory arena
mov es, di ; We may be freeing what is in ES
mov dx,id ; Get id to match with
or dx,dx ; Is it zero?
jnz short all1 ; No, continue
call GetDefOwner ; Yes, CX = default task owner to free
mov dx,cx
all1:
if SDEBUG
mov esi,[di].phi_first ; ES:DI points to first arena entry
mov cx,[di].hi_count ; CX = #entries in the arena
all2:
cmp ds:[esi].pga_owner,dx
jne short all3
mov ax, ds:[esi].pga_handle
Handle_To_Sel al
push cx
push dx
cCall DebugFreeSegment,<ax,0>
pop dx
pop cx
all3:
mov esi,ds:[esi].pga_next ; Move to next block
loop all2 ; Back for more if there (may go extra times
; because of coalescing, but no great whoop)
endif
call gfreeall
; REALLY free the id selector. MSTEST setup depends on this.
pushf
push ax
push bx
push es
push di
mov di,id
and di,0FFF8h
mov es,gdtdsc
push es:[di]
push es:[di + 2]
push es:[di + 4]
push es:[di + 6]
mov word ptr es:[di],0
mov word ptr es:[di + 2],0
mov word ptr es:[di + 4],0
mov word ptr es:[di + 6],0
mov bx,id
DPMICALL 000Ch
pop es:[di + 6]
pop es:[di + 4]
pop es:[di + 2]
pop es:[di]
pop di
pop es
pop bx
pop ax
popf
gf_done:
CheckHeap GlobalFreeAll
GLEAVE32
cEnd
;-----------------------------------------------------------------------;
; xhandle ;
; ;
; Returns the handle for a global segment. ;
; ;
; Arguments: ;
; Stack = sp -> near return return address ;
; sp+2 -> far return return address of caller ;
; sp+6 -> segment address parameter ;
; ;
; Returns: ;
; Old DS,DI have been pushed on the stack ;
; ;
; ZF= 1 if fixed segment. ;
; AX = handle ;
; ;
; ZF = 0 ;
; AX = handle ;
; BX = pointer to handle table entry ;
; CX = flags and count word from handle table ;
; DX = segment address ;
; ES:DI = arena header of object ;
; DS:DI = master object segment address ;
; ;
; Error Returns: ;
; AX = 0 if invalid segment address ;
; ZF = 1 ;
; ;
; Registers Preserved: ;
; ;
; Registers Destroyed: ;
; ;
; Calls: ;
; ;
; History: ;
; ;
; Thu Oct 16, 1986 02:40:08p -by- David N. Weise [davidw] ;
; Added this nifty comment block. ;
;-----------------------------------------------------------------------;
cProc xhandle,<PUBLIC,NEAR>
cBegin nogen
pop dx ; Get near return address
mov bx,sp ; Get seg parameter from stack
mov ax,ss:[bx+4]
cmp ax,-1 ; Is it -1?
jnz short xh1
mov ax,ds ; Yes, use callers DS
xh1: inc bp
push bp
mov bp,sp
push ds ; Save DS:DI
push edi
push esi
SetKernelDS FS
mov ds,pGlobalHeap ; Point to master object
xor edi,edi
inc [di].gi_lrulock
push dx
mov dx,ax
call pdref
xchg dx,ax ; get seg address in DX
jz short xhandle_ret ; invalid or discarded handle
test al, GA_FIXED
jnz short xhandle_fixed
or ax, ax
jmps xhandle_ret
xhandle_fixed:
xor bx, bx ; Set ZF
xhandle_ret:
ret
UnSetKernelDS FS
cEnd nogen
cProc GlobalHandleNorip,<PUBLIC,FAR>
; parmW seg
cBegin nogen
ifdef WOW
call xhandle
else
if KDEBUG
call xhandle_norip
else ; !WOW
call xhandle
endif
endif ; !WOW
mov ebx, esi
jmp xhandlex
cEnd nogen
cProc IGlobalHandle,<PUBLIC,FAR>
parmW selector
cBegin
cCall MyLock,<selector>
xchg ax, dx
cEnd
cProc MyLock,<PUBLIC,NEAR>
; parmW seg
cBegin nogen
mov bx, sp
xor ax, ax ; In case LAR fails
xor dx, dx
lar ax, ss:[bx+2]
jnz SHORT ML_End ; LAR failed, get out
test ah, DSC_PRESENT
jz short @F
push ds ; Do quick conversion for present
SetKernelDS ; selector
mov ds, pGlobalHeap
UnSetKernelDS
cCall get_arena_pointer32,<ss:[bx+2]>
or eax, eax
jnz SHORT got_arena_pointer
;** Fix for bug #9106 and (I think) #9102
;** If we get here, it's only because get_arena_pointer failed.
;** This happens with any non-heap selector.
pop ds
jmp SHORT ML_End ;Return NULL instead of GP faulting
got_arena_pointer:
mov ax, ds:[eax].pga_handle
ml_ret:
pop ds
mov dx, ax
Handle_To_Sel al
ML_End:
ret 2
@@:
pop ax ; Convert to far call for xhandle
push cs
push ax
call xhandle
xchg ax, dx
jmp xhandlex
cEnd nogen
cProc ILockSegment,<PUBLIC,FAR>
; parmW seg
cBegin nogen
call xhandle ; Get handle
jnz ls5 ; Ignore invalid or discarded objects
jmp xhandlex
ls5:
test cl,GA_DISCARDABLE
jz short xhandlex
call glock
jmps xhandlex
cEnd nogen
cProc IGlobalFix,<PUBLIC,FAR>
; parmW seg
cBegin nogen
call xhandle ; Get handle
jz short xhandlex ; Ignore invalid or discarded objects
call glock
jmps xhandlex
cEnd nogen
cProc IUnlockSegment,<PUBLIC,FAR>
; parmW seg
cBegin nogen
call xhandle ; Get handle
jz short xhandlex ; Ignore invalid or discarded objects
test cl,GA_DISCARDABLE
jz short xhandlex
call gunlock
jmps xhandlex
cEnd nogen
cProc IGlobalUnfix,<PUBLIC,FAR>
; parmW seg
cBegin nogen
call xhandle ; Get handle
jz short xhandlex ; Ignore invalid or discarded objects
call gunlock
jmps xhandlex
cEnd nogen
cProc IGlobalSize,<PUBLIC,FAR>
; parmW handle
cBegin nogen
call xhandle ; Call ghandle with handle in DX
jnz short gs1 ; Continue if valid handle
or dx,dx
jnz short gs1
xor ax,ax ; Return zero if invalid handle
jmps xhandlex
gs1:
or esi, esi ; Can't be valid if arena ptr == 0
jz gs2
push eax
mov eax, ds:[esi].pga_size
shr eax, 4
mov cx, ax ; Return number paragraphs in CX
shr eax, 12
mov dx, ax
pop eax
mov ax, word ptr ds:[esi].pga_size
push ds
push dx
push ax
cCall hackcheck,<handle>
or ax,ax
jz gsN
pop ax
pop dx
mov ax,04000h
xor dx,dx
push dx
push ax
gsN:
pop ax
pop dx
pop ds
jmps xhandlex
gs2:
xor ax, ax
xor dx, dx
jmps xhandlex
cEnd nogen
cProc IGlobalFlags,<PUBLIC,FAR>
; parmW handle
cBegin nogen
call xhandle ; Call ghandle with handle in DX
xchg cl,ch ; Return lock count in low half
mov ax,cx ; Let caller do jcxz to test failure
xhandlex:
call gleave
mov es, di ; don't return arbitrary selector
mov fs, di
pop esi
pop edi
pop ds
pop bp
dec bp
ret 2
cEnd nogen
if 0
cProc IGlobalLock,<PUBLIC,FAR>
; parmW handle
cBegin nogen
call xhandle ; Call ghandle with handle in DX
jz short lock1 ; Ignore invalid or discarded objects
if KDEBUG
cmp ch,0FFh ; Debugging check for count overflow
jne short lock0
push bx
push cx
push dx
xor cx,cx
kerror ERR_GMEMLOCK,<GlobalLock: Object usage count overflow>,cx,bx
pop dx
pop cx
pop bx
lock0:
endif
test cl,GA_DISCARDABLE
jz short lock1
call glock ; Increment lock count
lock1:
xor ax,ax
mov cx,dx
xhandlex1:
jmp short xhandlex
cEnd nogen
else
cProc IGlobalLock,<PUBLIC,FAR>,<ds>
parmW handle
ifdef WOW
localW gflags
localW accword
endif
cBegin
ifdef WOW
mov gflags,0
endif
xor dx, dx ; Assume failure
cmp handle, -1
jne short @F
mov handle, ds
@@:
lar eax, dword ptr handle
shr eax, 8
ifdef WOW
mov accword, ax
endif
test al, DSC_PRESENT ; Is it present?
jz short GL_exit
mov dx, handle ; OK, will return something
Handle_To_Sel dl ; Turn parameter into a selector
ifndef WOW
test ah, DSC_DISCARDABLE ; Is it discardable
jz short GL_exit ; no, Lock is a nop
endif
SetKernelDS es
mov ds, pGlobalHeap
cCall get_arena_pointer32,<dx> ; Discardable, get its arena
or eax, eax
jz short GL_exit ; No arena, assume an alias
ifdef WOW
mov cl, ds:[eax].pga_flags
mov byte ptr gflags, cl
test accword, DSC_DISCARDABLE SHL 8
jz GL_exit
endif
inc ds:[eax].pga_count ; Finally, do the lock
if KDEBUG
jnz short GL_exit ; Rip if we overflow
push bx
mov bx, handle
xor cx,cx
kerror ERR_GMEMLOCK,<GlobalLock: Object usage count overflow>,cx,bx
pop bx
endif
UnSetKernelDS es
GL_exit:
ifdef WOW
test gflags, GAH_CURSORICON
jz GL_NotIcon
push dx ; save
push handle ; arg for CursorIconLockOp
push FUN_GLOBALLOCK ; func id
call WowCursorIconOp
pop dx ; restore
GL_NotIcon:
endif
xor ax, ax
mov es, ax ; Clean out ES
mov cx, dx ; HISTORY - someone probably does a jcxz
cEnd
endif
cProc IGlobalUnlock,<PUBLIC,FAR>,<ds>
parmW handle
ifdef WOW
localW gflags
localW accword
endif
cBegin
mov gflags,0
cmp handle, -1
jne short @F
mov handle, ds
@@:
;
; Does this thing have any ring bits or LDT bit? If not, then it
; could be a selector incorrectly converted to a handle.
;
test byte ptr handle,7
jnz SHORT @F
if KDEBUG
Trace_Out "GlobalUnlock:"
push seg ThisIsForTurboPascal
push offset ThisIsForTurboPascal
cCall OutputDebugString
int 3
endif
dec handle
@@:
xor cx, cx ; Assume zero lock count
lar eax, dword ptr handle
shr eax, 8
ifdef WOW
mov accword, ax
endif
test al, DSC_PRESENT ; Is it present?
jz short GU_exit ; no, must be discarded, return 0:0
ifndef WOW
test ah, DSC_DISCARDABLE ; Is it discardable
jz short GU_exit ; no, Lock is a nop
endif
SetKernelDS es
mov ds, pGlobalHeap
cCall get_arena_pointer32,<handle> ; Discardable, get its arena
or eax, eax
jz short GU_exit ; No arena, assume an alias
ifdef WOW
push cx
mov cl,ds:[eax].pga_flags
mov byte ptr gflags, cl
pop cx
test accword, DSC_DISCARDABLE SHL 8
jz GU_exit
endif
mov cl, ds:[eax].pga_count ; Get current count
dec cl
cmp cl, 0FEh
jae short @F
dec ds:[eax].pga_count ; Finally, do the unlock
jmps GU_Exit
@@:
if KDEBUG
push bx ; then the count is wrong.
push dx
mov bx, handle
xor cx,cx
kerror ERR_GMEMUNLOCK,<GlobalUnlock: Object usage count underflow>,cx,bx
pop dx
pop bx
endif
xor cx, cx
UnSetKernelDS es
GU_exit:
ifdef WOW
test gflags, GAH_CURSORICON
jz GUL_NotIcon
push cx ; save
push handle ; arg for CursorIconLockOp
push FUN_GLOBALUNLOCK ; UnLocking
call WowCursorIconOp
pop cx ; restore
GUL_NotIcon:
endif
xor ax, ax
mov es, ax ; Clean out ES
mov ax, cx
; Smalltalk V version 1.1 has a bug where they depend on dx containing
; the handle as it did in 3.0. Sinc STalk is a 386 only app, this is
; only put into the 386 kernel
mov dx, handle
cEnd
;-----------------------------------------------------------------------;
; GlobalWire ;
; ;
; Locks a moveable segment and moves it down as low as possible. ;
; This is meant for people who are going to be locking an object ;
; for a while and wish to be polite. It cannot work as a general ;
; panacea, judgement is still called for in its use! ;
; ;
; Arguments: ;
; WORD object handle ;
; ;
; Returns: ;
; DWORD object address ;
; ;
; Error Returns: ;
; ;
; Registers Preserved: ;
; ;
; Registers Destroyed: ;
; ;
; Calls: ;
; xhandle ;
; gmovebusy ;
; ;
; History: ;
; ;
; Wed Dec 03, 1986 01:07:13p -by- David N. Weise [davidw] ;
; Wrote it. ;
;-----------------------------------------------------------------------;
cProc IGlobalWire,<PUBLIC,FAR>
; parmW handle
cBegin nogen
if KDEBUG
push ds
SetKernelDS
cmp [fBooting], 0
jnz shutup
push bx
mov bx, sp
mov bx, ss:[bx+8]
krDebugOut <DEB_WARN OR DEB_KrMemMan>, "GlobalWire(#BX of %BX2) (try GlobalLock)"
pop bx
shutup:
pop ds
UnSetKernelDS
endif
call xhandle
jz short gw_done ; Ignore invalid or discarded objects
call gwire ; Copy it low if possible
inc ds:[esi].pga_count ; Lock it down.
test ds:[esi].pga_flags,GA_DISCCODE
jz short not_disccode
call glrudel
and ds:[esi].pga_flags,NOT GA_DISCCODE
not_disccode:
mov ax, ds:[esi].pga_handle
Handle_To_Sel al ; Return address.
gw_done:
mov dx,ax
xor ax,ax ; Make address SEG:OFF.
jmp xhandlex
cEnd nogen
cProc gwire,<PUBLIC,NEAR>
cBegin nogen
ReSetKernelDS fs
or Kernel_Flags[1],kf1_MEMORYMOVED
push ax ; Save handle
push cx
test cl,GA_DISCARDABLE
jz short @F
inc ds:[esi].pga_count ; don't want to discard if discardable
@@: xor ax,ax ; Try to get a fixed segment.
mov ebx,ds:[esi].pga_size
mov cx,ds:[esi].pga_owner
call gsearch ; AX = segment
pop cx
pop bx ; Object handle.
push eax ; Return from gsearch
cCall get_arena_pointer32,<bx> ; Get arena header, gsearch may
; have moved the global object!
mov esi,eax ; ESI is old block
test cl,GA_DISCARDABLE
jz short @F
dec ds:[esi].pga_count ; undo lock
@@:
pop eax ; EAX is new block
or eax,eax
push bx ; Handle
jz short lock_in_place ; Couldn't get memory.
mov ebx, ds:[eax].pga_address
cmp ebx, ds:[esi].pga_address
jbe short ok_to_move ; Let's not move it up in memory!!
cCall PreAllocArena
jz short lock_in_place
push esi
mov esi, eax
xor edx, edx
call gmarkfree
pop esi
jmp short lock_in_place
ok_to_move:
mov edx, esi
mov esi, eax
mov ebx,ga_next ; This is always an exact fit.
call gmovebusy ; Wire it on down.
lock_in_place:
pop bx ; Handle
ret
UnSetKernelDS fs
cEnd nogen
;-----------------------------------------------------------------------;
; GlobalUnWire ;
; ;
; ;
; Arguments: ;
; ;
; Returns: ;
; ;
; Error Returns: ;
; ;
; Registers Preserved: ;
; ;
; Registers Destroyed: ;
; ;
; Calls: ;
; ;
; History: ;
; ;
; Wed Sep 16, 1987 04:28:49p -by- David N. Weise [davidw] ;
; Wrote it. ;
;-----------------------------------------------------------------------;
cProc IGlobalUnWire,<PUBLIC,FAR>
; parmW handle
cBegin nogen
call xhandle
jz short guw_done
if 0
mov bx, ax
sel_check bx
SetKernelDS es
mov es, gdtdsc
UnSetKernelDS es
test byte ptr es:[bx+6], 10h
jz short guw_not_disccode
test byte ptr es:[bx+5], 8 ; Is it code?
jz short guw_not_disccode ; nope, no point setting it
else
lar ebx, eax
shr ebx, 8
test bh, DSC_DISCARDABLE
jz short guw_not_disccode
test bl, DSC_CODE_BIT ; Is it code?
jz short guw_not_disccode ; nope, no point setting it
endif
or ds:[esi].pga_flags,GA_DISCCODE
call glruadd
guw_not_disccode:
if KDEBUG
cmp ch,00h ; Debugging check for count underflow
jne short unlock1
push bx ; then the count is wrong.
push cx
push dx
xor cx,cx
kerror ERR_GMEMUNLOCK,<GlobalUnWire: Object usage count underflow>,cx,bx
pop dx
pop cx
pop bx
unlock1:
endif
call gunlock
mov ax, 0FFFFh ; TRUE
jcxz guw_done
inc ax ; FALSE
guw_done:
jmp xhandlex
cEnd nogen
;-----------------------------------------------------------------------;
; GlobalCompact ;
; ;
; Compacts the global arena until a free block of the requested size ;
; appears. Contrary to the toolkit it ALWAYS compacts! ;
; ;
; Arguments: ;
; DWORD minimum bytes wanted ;
; ;
; Returns: ;
; ;
; Error Returns: ;
; ;
; Registers Preserved: ;
; ;
; Registers Destroyed: ;
; ;
; Calls: ;
; ;
; History: ;
; ;
; Wed 26-Apr-1989 15:33:18 -by- David N. Weise [davidw] ;
; Added the zero'ing of ES on exit. ;
; ;
; Wed Dec 03, 1986 01:09:02p -by- David N. Weise [davidw] ;
; Added this nifty comment block. ;
;-----------------------------------------------------------------------;
cProc GlobalCompact,<PUBLIC,FAR>
parmD minBytes
localD DPMIbytes
cBegin
GENTER32 ; About to modify memory arena
CheckHeap GlobalCompact
call GetDPMIFreeSpace ; EAX = largest free DPMI block
and ax, GA_MASK_BYTES
mov ebx, eax
clc
call galign ; align size
mov eax, edx ; EAX = aligned DPMI block
mov DPMIbytes, eax
cmp eax, minBytes ; Q: Enough to satisfy request?
jb SHORT GCReallyCompact ; N: Really compact heap
cmp eax, 512*1024 ; Q: Less than 1/2 Mb of DPMI mem?
jnb SHORT GCWorked
GCReallyCompact:
if KDEBUG
push ax
push bx
mov ax, seg_minBytes
mov bx, off_minBytes
krDebugOut DEB_WARN, "%SS2 GlobalCompact(#ax#BX), discarding segments"
pop bx
pop ax
endif
mov ax,-1
lea bx,minBytes
call gbtop
assumes es, nothing
clc ; galign should be called with CF = 0
call galign
call gavail ; Returns paragraphs in DX:AX
cmp eax, DPMIbytes ; Return max of gavail or DMPI free
jae SHORT GCWorked ; space
mov eax, DPMIbytes
GCWorked:
mov edx, eax
shr edx, 16
mov cx, ax
or cx, dx
GLEAVE32
pushad
call ShrinkHeap
popad
cEnd
;-----------------------------------------------------------------------;
; GlobalNotify ;
; ;
; This sets a procedure to call when a discardable segment belonging ;
; to this task gets discarded. The discardable object must have been ;
; allocated with the GMEM_DISCARDABLE bit set. ;
; ;
; Arguments: ;
; parmD NotifyProc ;
; ;
; Returns: ;
; nothing ;
; ;
; Error Returns: ;
; ;
; Registers Preserved: ;
; AX,CX,DX,DI,SI,DS ;
; ;
; Registers Destroyed: ;
; BX,ES ;
; ;
; Calls: ;
; nothing ;
; ;
; History: ;
; ;
; Tue Jun 23, 1987 10:16:32p -by- David N. Weise [davidw] ;
; Wrote it. ;
;-----------------------------------------------------------------------;
cProc IGlobalNotify,<PUBLIC,FAR>
parmD NotifyProc
cBegin
push ds
les bx,NotifyProc ; verify pointer
SetKernelDS
mov ds,curTDB
UnSetKernelDS
mov word ptr ds:[TDB_GNotifyProc][2],es
mov word ptr ds:[TDB_GNotifyProc][0],bx
pop ds
cEnd
cProc GlobalMasterHandle,<PUBLIC,FAR>
cBegin nogen
push ds
SetKernelDS
mov ax,hGlobalHeap
mov dx,pGlobalHeap
UnSetKernelDS
pop ds
ret
cEnd nogen
;-----------------------------------------------------------------------;
; GetTaskDS ;
; ;
; Gets the segment of the current task's DS. ;
; ;
; Arguments: ;
; none ;
; ;
; Returns: ;
; AX = selector. ;
; DX = selector. ;
; ;
; Error Returns: ;
; ;
; Registers Preserved: ;
; ;
; Registers Destroyed: ;
; ;
; Calls: ;
; nothing ;
; ;
; History: ;
; ;
; Thu Jun 25, 1987 10:52:10p -by- David N. Weise [davidw] ;
; Wrote it. ;
;-----------------------------------------------------------------------;
cProc GetTaskDS,<PUBLIC,FAR>
cBegin nogen
push ds
SetKernelDS
mov ds,curTDB
UnsetKernelDS
mov ax,ds:[TDB_Module]
mov dx,ax
pop ds
ret
cEnd nogen
assumes ds,nothing
assumes es,nothing
cProc IGlobalLRUOldest,<PUBLIC,FAR>
; parmW handle
cBegin nogen
call xhandle ; Call ghandle with handle in DX
jz short xhandlex2
call glrubot
xhandlex2:
jmp xhandlex
cEnd nogen
cProc IGlobalLRUNewest,<PUBLIC,FAR>
; parmW handle
cBegin nogen
call xhandle ; Call ghandle with handle in DX
jz short xhandlex2
call glrutop
jmp xhandlex
cEnd nogen
;-----------------------------------------------------------------------;
; SwitchStackTo ;
; ;
; Switched to the given stack, and establishes the BP chain. It also ;
; copies the last stack arguments from the old stack to the new stack. ;
; ;
; Arguments: ;
; parmW new_ss ;
; parmW new_sp ;
; parmW stack_top ;
; ;
; Returns: ;
; A new stack! ;
; ;
; Error Returns: ;
; ;
; Registers Preserved: ;
; DI,SI,DS ;
; ;
; Registers Destroyed: ;
; AX,BX,CX,DX,ES ;
; ;
; Calls: ;
; nothing ;
; ;
; History: ;
; ;
; Tue Sep 22, 1987 08:42:05p -by- David N. Weise [davidw] ;
; Wrote it. ;
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProcVDO SwitchStackTo,<PUBLIC,FAR>
; parmW new_ss
; parmW new_sp
; parmW stack_top
cBegin nogen
SetKernelDS es
FCLI
mov GSS_SI,si
mov GSS_DS,ds
pop word ptr GSS_RET[0] ; get the return address
pop word ptr GSS_RET[2]
assumes es, nothing
pop ax ; stack_top
pop bx ; new_sp
pop dx ; new_ss
mov si,bp ; Calculate # of parameters on stack.
dec si ; remove DS
dec si
mov cx,si
sub cx,sp
shr cx,1
push bp ; save BP
smov es,ss
mov ds,dx ; new_ss
mov ds:[2],sp
mov ds:[4],ss
mov ds:[pStackTop],ax
mov ds:[pStackMin],bx
mov ds:[pStackBot],bx
; switch stacks
mov ss,dx
mov sp,bx
mov bp,bx
xor ax,ax
push ax ; null terminate bp chain
jcxz no_args
copy_args:
dec si
dec si
push es:[si]
loop copy_args
no_args:
SetKernelDS
mov es,curTDB
mov es:[TDB_taskSS],ss
mov es:[TDB_taskSP],sp
push GSS_RET.sel
push GSS_RET.off ; get the return address
mov si,GSS_SI
mov ds,GSS_DS
FSTI
ret
cEnd nogen
;-----------------------------------------------------------------------;
; SwitchStackBack ;
; ;
; Switches to the stack stored at SS:[2], and restores BP. Preserves ;
; AX and DX so that results can be passed back from the last call. ;
; ;
; Arguments: ;
; none ;
; ;
; Returns: ;
; The old stack! ;
; ;
; Error Returns: ;
; ;
; Registers Preserved: ;
; AX,DX,DI,SI,DS ;
; ;
; Registers Destroyed: ;
; BX,CX,ES ;
; ;
; Calls: ;
; nothing ;
; ;
; History: ;
; ;
; Tue Sep 22, 1987 09:56:32p -by- David N. Weise [davidw] ;
; Wrote it. ;
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc SwitchStackBack,<PUBLIC,FAR>
cBegin nogen
push ds
SetKernelDS
FCLI
pop GSS_DS
pop GSS_RET.off ; get the return address
pop GSS_RET.sel
xor bx,bx
xor cx,cx
xchg bx,ss:[4]
xchg cx,ss:[2]
mov ss,bx
mov sp,cx
mov es,curTDB
mov es:[TDB_taskSS],ss
mov es:[TDB_taskSP],sp
pop bp
push GSS_RET.sel
push GSS_RET.off ; get the return address
mov ds,GSS_DS
UnSetKernelDS
FSTI
ret
cEnd nogen
;-----------------------------------------------------------------------;
; GetFreeMemInfo ;
; ;
; Get free and unlocked pages in paging system ;
; ;
; Arguments: ;
; none ;
; ;
; Returns: ;
; DX Free pages ;
; AX Unlocked pages ;
; ;
; Error Returns: ;
; ;
; Registers Preserved: ;
; DI,SI,DS ;
; ;
; Registers Destroyed: ;
; ES ;
; ;
; Calls: ;
; nothing ;
; ;
; History: ;
; ;
;-----------------------------------------------------------------------;
assumes ds, nothing
assumes es, nothing
cProc GetFreeMemInfo,<PUBLIC,FAR>,<di>
localV mem_info,30h
cBegin
mov ax, -1
mov dx, ax
SetKernelDS es
test byte ptr WinFlags[1], WF1_PAGING
jz short gfmi_no_info
lea di, mem_info
smov es, ss
UnSetKernelDS es
DPMICALL 0500h ; Get Free Memory Information
jc short gfmi_no_info
mov ax, es:[di][10h]
mov dx, es:[di][14h]
gfmi_no_info:
cEnd
;-----------------------------------------------------------------------;
; GetFreeSpace ;
; ;
; Calculates the current amount of free space ;
; ;
; Arguments: ;
; flags - ignored for non-EMS system ;
; ;
; Returns: ;
; DX:AX Free space in bytes ;
; ;
; Error Returns: ;
; ;
; Registers Preserved: ;
; DI,SI,DS ;
; ;
; Registers Destroyed: ;
; BX,CX,ES ;
; ;
; Calls: ;
; nothing ;
; ;
; History: ;
; ;
; Wed 26-Apr-1989 15:33:18 -by- David N. Weise [davidw] ;
; Added the zero'ing of ES on exit. ;
; ;
;-----------------------------------------------------------------------;
assumes ds, nothing
assumes es, nothing
cProc IGetFreeSpace,<PUBLIC,FAR>
parmW flags
cBegin
GENTER32
call GetDPMIFreeSpace ; EDX = Free DPMI heap space
mov esi, [di].phi_first
gfs_loop:
mov esi, ds:[esi].pga_next
cmp ds:[esi].pga_sig, GA_ENDSIG
je short gfs_last ; End of heap
mov ax, ds:[esi].pga_owner
cmp ax, GA_NOT_THERE
je short gfs_loop ; Nothing there
or ax, ax ; Free?
jz short gfs_include ; yes, include
test flags, 2 ; Ignore discardable?
jnz short gfs_loop ; yes.
mov bx, ds:[esi].pga_handle
test bl, GA_FIXED
jnz short gfs_loop ; Fixed block if odd
cmp ds:[esi].pga_sig, 0
jne short gfs_loop ; skip if locked
lar ebx, ebx
shr ebx, 8
test bh, DSC_DISCARDABLE ; include if discardable
jz short gfs_loop
gfs_include:
add edx, ds:[esi].pga_size
jmps gfs_loop
gfs_last:
test flags, 2 ; Ignoring discardable?
jnz short @F ; yes, then ignore fence
sub edx, [di].gi_reserve ; Subtract out that above fence
@@:
sub edx, 10000h ; Lose 64k of it for fun
jns short gfs_positive ; Return zero if we
xor edx, edx ; went negative!
gfs_positive:
;
; Now check to see if this app has troubles if the value gets too huge.
; 61a8000h is 100MB
;
WOW_FREE_SPACE_CAP equ 61a8000h
push edx
cCall MyGetAppWOWCompatFlags ; check if we need to cap it
test dx, WOWCF_LIMIT_MEM_FREE_SPACE SHR 16
pop edx
jz short @f
cmp edx, WOW_FREE_SPACE_CAP
jb short @f
mov edx, WOW_FREE_SPACE_CAP
@@:
mov eax, edx ; Return in DX:AX
shr edx, 16
GLEAVE32
cEnd
;-----------------------------------------------------------------------;
; GetDPMIFreeSpace ;
; ;
; Calculates the current amount of DPMI free space ;
; ;
; Arguments: ;
; None ;
; ;
; Returns: ;
; EAX = Size of largest free block in bytes ;
; EDX = Free DPMI space in bytes ;
; DI = 0 ;
; ;
; Error Returns: ;
; ;
; Registers Preserved: ;
; DI,SI,DS ;
; ;
; Registers Destroyed: ;
; BX,CX,ES ;
; ;
; Calls: ;
; nothing ;
; ;
; History: ;
; ;
;-----------------------------------------------------------------------;
assumes ds, nothing
assumes es, nothing
ifdef WOW
cProc GetDPMIFreeSpace,<PUBLIC,NEAR>,<edi,esi,cx>
cBegin
push bp
mov cx, sp
and cx, 3 ;prepare to align on dword
add cx, SIZE GMEMSTATUS_block ;length to adjust sp
sub sp, cx
mov bp, sp ;base pointer to structure
mov dwLength[bp], SIZE GMEMSTATUS_block
cCall GlobalMemoryStatus,<ss,bp> ;Call NT To get Memory Info
mov edx,dwAvailPhys[bp] ; if (dwAvailVirtual < dwAvailPhys +dwAvailPagefile)
add edx,dwAvailPageFile[bp] ; return(dwAvailVirtual
cmp dwAvailVirtual[bp],edx ; else
ja @f ; return(dwAvailPhys +dwAvailPagefile)
mov edx,dwAvailVirtual[bp]
@@:
mov eax,dwAvailPhys[bp] ; Not entirely accurate equivalent
; of Windows, should be OK
add sp, cx ;restore stack pointer
pop bp
else; NOT WOW
cProc GetDPMIFreeSpace,<PUBLIC,NEAR>
localV mem_info,30h
cBegin
xor edx, edx ; In case of DPMI failure
lea di, mem_info
smov es, ss
DPMICALL 0500h ; Get Free Memory Information
jc short xoredxedx
mov edx, dword ptr mem_info[14h] ; Number of free pages (if not paging)
mov eax, dword ptr mem_info[20h] ; Paging file size
inc eax
cmp eax, 1 ; 0 or -1?
jbe short not_paging ; yes, no paging
lea edx, [eax-1] ; no, paging file size in edx
;
; Calculation is:
; (Paging file size + Total physical pages)
; - (Total linear space - Free linear space)
;
; Actually, there are two limits to total swap area. (Since Win386
; isn't a planned product, it first allocates data structures for
; linear memory, then discovers how big the page file is.)
; First, find out how many pages we have - this is the sum of
; physical pages owned by DPMI, and pages in the disk swap file.
; Next, find out how many pages are allowed for in the linear
; address data structure. The lesser of these two values is
; the limit. Next, subtract the already allocated pages. This
; is found as the difference between total linear, and free linear
; space. The final result is close to the amount of allocatable
; virtual memory.
add edx, dword ptr mem_info[18h] ; Total physical pages
cmp edx, dword ptr mem_info[0ch] ; Allocatable linear memory
jl short @F
mov edx, dword ptr mem_info[0ch] ; take the smaller
@@:
add edx, dword ptr mem_info[1Ch] ; Free linear space
sub edx, dword ptr mem_info[0Ch] ; Total linear space
not_paging:
mov eax, dword ptr mem_info ; size of largest free block
shl edx, 12 ; Convert to bytes
jns short no_info ; Went negative?
xor edx, edx
endif: WOW
no_info:
;
; !!! HACK ALERT !!!
; We don't actually want to grab all the memory from DPMI, because then
; we won't be able to allocate DPMI memory for arena tables, if we
; need them, and WIN386 won't be able to grow the LDT.
;
sub edx,10000h
ja @F
xoredxedx:
xor edx,edx
@@:
cmp eax,edx
jb @F
mov eax,edx
@@:
xor di, di
cEnd
;-----------------------------------------------------------------------;
; GlobalDOSAlloc
;
; Allocates memory that is accessible by DOS.
;
; Entry:
; parmD nbytes number of bytes to alloc
;
; Returns:
; AX = memory handle
; DX = DOS segment paragraph address
;
; History:
; Tue 23-May-1989 11:30:57 -by- David N. Weise [davidw]
; Wrote it!
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc GlobalDOSAlloc,<PUBLIC,FAR>,<di,si>
parmD nbytes
cBegin
mov ax,GA_ALLOC_DOS shl 8
cCall IGlobalAlloc,<ax,nbytes>
xor dx, dx ; In case of error return
or ax, ax
jz short gda_exit
push ax
cCall get_physical_address,<ax>
REPT 4
shr dx, 1
rcr ax, 1
ENDM
mov dx, ax
pop ax
gda_exit:
cEnd
;-----------------------------------------------------------------------;
; GlobalDOSFree
;
; Frees memory allocated by GlobalDOSAlloc.
;
; Entry:
; parmW handle
;
; Returns:
;
; Registers Destroyed:
;
; History:
; Tue 23-May-1989 17:48:03 -by- David N. Weise [davidw]
; Wrote it!
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc GlobalDOSFree,<PUBLIC,FAR>,<di,si>
parmW handle
cBegin
cCall IGlobalFree,<handle>
cEnd
;-----------------------------------------------------------------------;
; GlobalPageLock
;
; Page locks the memory associated with the Handle.
;
; Entry:
; parmW handle
;
; Returns:
; AX = new lock count
;
; History:
; Wed 31-May-1989 22:14:21 -by- David N. Weise [davidw]
; Wrote it!
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc IGlobalPageLock,<PUBLIC,FAR>
; parmW handle
cBegin nogen
call xhandle
or ax,ax
jz short gpl_fail ; Ignore invalid or discarded objects
cmp [esi].pga_pglock, 0FFh ; About to overflow?
je short gpl_over
push dx
call gwire ; Move it LOW!
pop bx
ifndef WOW
DPMICALL 4 ; Page Lock it
jc short gpl_fail
endif
inc [esi].pga_count
inc [esi].pga_pglock
movzx ax, [esi].pga_pglock
jmp xhandlex
gpl_over:
if KDEBUG
push bx
push cx
push dx
xor cx,cx
kerror ERR_GMEMLOCK,<GlobalPageLock: Lock count overflow>,cx,bx
pop dx
pop cx
pop bx
endif
gpl_fail:
xor ax,ax
jmp xhandlex
cEnd nogen
;-----------------------------------------------------------------------;
; GlobalPageUnlock
;
; Page unlocks the memory associated with the Handle.
;
; Entry:
; parmW handle
;
; Returns:
; AX = new lock count
;
; History:
; Wed 31-May-1989 22:14:21 -by- David N. Weise [davidw]
; Wrote it!
;-----------------------------------------------------------------------;
assumes ds,nothing
assumes es,nothing
cProc IGlobalPageUnlock,<PUBLIC,FAR>
; parmW handle
cBegin nogen
call xhandle
or ax,ax
jz short gpu_fail ; Ignore invalid or discarded objects
cmp [esi].pga_pglock, 0 ; About to underflow?
je short gpu_under
mov bx, dx
ifndef WOW
DPMICALL 5
jc short gpu_fail
endif
dec [esi].pga_count
dec [esi].pga_pglock
movzx ax, [esi].pga_pglock
jmp xhandlex
gpu_under:
if KDEBUG
xor ax,ax
push bx
push cx
push dx
xor cx,cx
kerror ERR_GMEMUNLOCK,<GlobalPageUnlock: Lock count underflow>,cx,bx
pop dx
pop cx
pop bx
endif
gpu_fail:
xor ax, ax
jmp xhandlex
cEnd nogen
;
; Win95 implements GlobalSmartPageLock and GlobalSmartPageUnlock
; here in 3ginterf.asm. These routines will page-lock the given
; global memory object only if the system is paging via DOS (as
; opposed to 32-bit Disk Access), otherwise the memory is locked
; in linear memory using GlobalFix. Callers use these routines
; for memory which may be accessed while handling an Int 21, to
; prevent re-entering DOS. Since we never page via Int 21, we
; simply export GlobalFix as GlobalSmartPageLock and GlobalUnfix
; as GlobalSmartPageUnlock.
;
ifdef WOW
;--------------------------------------------------------------------------;
;
; Similar to GlobalFlags
;
;--------------------------------------------------------------------------;
cProc SetCursorIconFlag,<PUBLIC,FAR>,<ds,es,esi>
parmW handle
parmW fSet
cBegin
SetKernelDS es
mov ds, pGlobalHeap
UnSetKernelDS
cCall get_arena_pointer32,<handle> ; get the owner
or eax,eax
jz sf_error
mov esi,eax
mov ax,fSet
or ax,ax
jz sf_unset
or ds:[esi].pga_flags, GAH_CURSORICON ;cursor, icon, or accelerator
jmps sf_error
sf_unset:
and ds:[esi].pga_flags, NOT GAH_CURSORICON
sf_error:
xor ax,ax
cEnd
;--------------------------------------------------------------------------;
;
; Stamp the 01h in globalarena for DDE handles. This is GAH_PHANTOM flag
; which is not used any longer.
;
;--------------------------------------------------------------------------;
cProc SetDdeHandleFlag,<PUBLIC,FAR>,<ds,es,esi>
parmW handle
parmW fSet
cBegin
SetKernelDS es
mov ds, pGlobalHeap
UnSetKernelDS
cCall get_arena_pointer32,<handle> ; get the owner
or eax,eax
jz sd_error
mov esi,eax
mov ax,fSet
or ax,ax
jz sd_unset
or ds:[esi].pga_flags, GAH_WOWDDEFREEHANDLE
jmps sd_error
sd_unset:
and ds:[esi].pga_flags, NOT GAH_WOWDDEFREEHANDLE
sd_error:
xor ax,ax
cEnd
endif
sEnd CODE
end