;       SCCSID = @(#)dosmem.asm 6.3 91/09/22
TITLE   DOSMEM.ASM - External debugger commands for OS/2
.286p

;***    DOSMEM.ASM
;
SCCSID equ "@(#)dosmem.asm      6.3 91/09/22"
;
;       Routines to perform commands that are external to the debugger
;       and are environment dependent.  These are commands that are
;       specific to OS/2 and use OS/2 data structures.
;
; Modification:
;********************************************************************
;82818 ChangeTeam 02/07/95                                    ;82818
;82818     Moving r206 debug .mk command to R207              ;82818
;72417 MLM        11/18/95
;          Moved find.inc after tkexport.inc as part of reducing
;          FSCRIT serialization.
;153574 RJM 2 May 1996 Fix .MPFL .MPFR and .MPI
;154741 RJM 15 May 1996 Fix .MVFL and .MVFR hangs
;155843 RJM 13 Jum 1996 fix .MK  - DOAPrintLock called erroneously. 
;155843 RJM 13 Jun 1996 add support for 147968 (FSD DD allocs using HMTE)

INCL_MI =       1

.xlist
        include fnodeb.inc
        include dosseg.inc
        include basemaca.inc
        include osmaca.inc
        include osconst.inc
        include mi.inc
        include ostypes.inc
        include dossymc.inc
        include pgexport.inc
        include vmexport.inc
        include vmowner.inc
        include sem.inc
        include screen.inc
        include proc.inc
        include sigdef.inc
        include except.inc
        include infoseg.inc
        include curdir.inc
        include dirent.inc
        include tkexport.inc
        include find.inc                        ;72417 moved after tkexport.inc
        include tkptda.inc
        include mvdmexp.inc
        include pglocal.inc
        include debseg.inc
        include debmac.inc
        include debequ.inc
        include debprt.inc
        include debdesc.inc
        include ldrvars.inc
.list
        CpuMode 386
        ModName DOSMEM, FNO_DOSMEM_ASM

LINES_PER_PAGE          equ     23

        ReferGlobal     MaxThreads,WORD

        ReferFlat       _parvmOne,dword
        ReferFlat       _pcovmOne,dword
        ReferFlat       _palVMAliases,dword
        ReferFlat       _pobvmOne,dword
        ReferFlat       _pft,dword
        ReferFlat       _pgPhysPages,dword
        ReferFlat       _pgPhysMax,dword
        ReferFlat       _pgpVPBase,dword
        ReferFlat       _pgpVPEnd,dword
        ReferFlat       _pgPageablePAI,dword
        ReferFlat       _pVMLIHead,dword         ;** 82818

DOAENTRY macro name
local a
ifdef DEBUG
    DDATA segment
        a db name, 0
    DDATA ends
    debprt <"hdl=%08lx f=%08lx cnt=%08lx hobptda=%04x si=%04x %s", CR, LF>,<edx,ebx,ecx,di,si,<offset a>>
endif
endm

DataSegmentStart

Extern  pTXT, WORD
Extern  DefType, BYTE
Extern  RegSA, WORD
Extern  VDMmsg, BYTE
Extern  SYIthreadmsg, BYTE
Extern  DisAddr, WORD           ; Disassembly address

Global  li_pvmli, DWORD, 0          ;82818
Global  li_cs, WORD, 0              ;82818
Global  li_eip, DWORD, 0            ;82818
Global  li_phlock, DWORD, 0         ;82818
Global  li_address, DWORD, 0        ;82818
Global  li_flg, WORD, 0             ;82818
Global  li_hptda, WORD, 0           ;82818
Global  li_npages, WORD, 0          ;82818
Global  li_hob, WORD, 0             ;82818
Global  li_sig, WORD, 0             ;82818
Global  li_csig, WORD, 0            ;82818

Global  DosLinAddr,STRUC, AddrS, <0, 0, EXPR_TYPE_LIN, 0>

;*      Prints a handle table entry

PrintObject     label   byte


OB_PSEUDOSHIFT  equ     15
.errnz ((1 shl OB_PSEUDOSHIFT) - OB_PSEUDO)

        OutBlanks 2
        JumpIfBitSet    <ob_fs - obu0>, OB_PSEUDOSHIFT, PrtObjPseudo
        JumpIfBitF      <ob_hobowner - obu0>, 0, 16, 0, PrtObjPseudo
        OutWordHexPtr   ob_har
        OutBlank
        OutWordHexPtr   ob_hobnext
        JumpOp          PrtObjRest

PrtObjPseudo label byte
        OutChar "%"
        OutWordHexPtr   <ob_va.HighWord - obu0>
        OutWordHexPtr   <ob_va.LowWord - obu0>
PrtObjRest label byte
        OutBlanks 2

        OutWordHexPtr   <ob_fs - obu0>
        OutBlank

        OutWordHexPtr   <ob_hobowner - obu0>
        OutBlank

        OutWordHexPtr   <ob_hobmte - obu0>
        OutBlanks 2

        OutWordHexPtr   <ob_wsemowner - obu0>
        OutBlank

        OutByteHexPtr   <ob_bsemcnt - obu0>
        OutBlanks 2

        OutByteHexPtr   <ob_cllock - obu0>
        OutBlank

;       OutByteHexPtr   <ob_cllockdev - obu0>
;       OutBlank

        OutByteHexPtr   <ob_cslock - obu0>
        OutBlank

;       OutByteHexPtr   <ob_xflags - obu0>
;       OutBlank

        OutByteHexPtr   <ob_xflags - obu0>
        OutBlank
        EndOp


; BUGBUG IDB - This stuff should be generated from vmexport.h
AR_HCOSHIFT     equ     9
.errnz  ((1 shl AR_HCOSHIFT) - AR_HCO)
AR_SELMAPSHIFT  equ     3
.errnz  ((1 shl AR_SELMAPSHIFT) - AR_SELMAP)
AR_TAGSHIFT     equ     0

;*      Prints an arena record

PrintArena      label   byte


        OutBlank
;;;;;;; OutWordHexPtr   ar_cpg.HighWord
;;;;;;; OutWordHexPtr   ar_cpg.LowWord
        OutStr          "000"
        OutBitFHexPtr   ar_union5, 0, 20, 5
        OutBlank

        OutChar "%"
        OutBitFHexPtr   ar_union0,                              \
                        LinPageTable,                           \
                        <width LinPageDir + width LinPageTable>,\
                        5                       ; ar_ipg
        OutStr  "000 "
        OutBitFHexPtr   ar_union0,              \
                        LinDataOffset,          \
                        <width LinDataOffset>,   \
                        3                       ; ar_f
        OutBlank

        OutWordHexPtr   <ar_harnext - aru0>
        OutBlank
        OutWordHexPtr   <ar_harprev - aru0>
        OutBlank
        OutWordHexPtr   <ar_harlink - aru0>
        OutBlank
        OutWordHexPtr   <ar_harhash - aru0>
        OutBlank

        OutWordHexPtr   <ar_hob - aru0>         ; or ar_hobgroup
        OutBlank
        OutWordHexPtr   <ar_hal - aru4>         ; ar_hal
        OutBlank

        JumpIfBitF      ar_union0, AR_TAGSHIFT, 1, 0, PrtArInval
        JumpIfBitF      ar_union0, AR_TAGSHIFT, 3, AR_TAGREG+AR_INUSE, PrtArReg
        JumpIfBitF      ar_union0, AR_TAGSHIFT, 3, AR_TAGSEN+AR_INUSE, PrtArSen
        JumpIfBitF      ar_union0, AR_TAGSHIFT, 3, AR_TAGBSEN+AR_INUSE, PrtArSen
        JumpOp  PrtArInval

;       BUGBUG IDB - Extend later to include other types of arena record

;       Sentinel or Boundary Sentinel Arena Record
;       ==========================================

PrtArSen label byte
        OutStr          "max=%"                 ; ipgmax field of sentinel
        OutBitFHexPtr   <ar_ipgmax - aru4>,0,20,5 ; ipgmax field of sentinel
        OutStr          "000"                   ; Convert pages to address
        JumpOp          PrtArCRLF

;       Regular Arena Record
;       ====================
;
;       Validate ar_hobptda/ar_hco/ar_sel field
;
;       If AR_HCO is set, field contains context record handle
;       ELSE
;         If system arena
;           If tiled, field contains GDT selector
;           ELSE field is invalid
;         ELSE
;           If field non-null assume field contains PTDA handle
;           BUGBUG - IDB We would have to check for private arena to
;                        decide this conclusively

PrtArReg label byte
        JumpIfBitF      ar_union0, AR_HCOSHIFT, 1, 0, PrtArChkSys
                                        ; Jump if AR_HCO not set
        OutStr          " hco="         ; hco - context record handle
        OutBitFHexPtr   ar_union5, 20, 1, 1
        JumpOp          PrtArRest

;; defect 75746 - moeved the system arena down to .5 gig.
; BUGBUG - The following 3 jumps assume that a virtual address is in the
;          system arena iff it is >= 20000000h

;PrtArChkSys label byte
;        JumpIfBitF      ar_union0, 31, 1, 1, PrtArChkTil
;        JumpIfBitF      ar_union0, 30, 1, 1, PrtArChkTil
;        JumpIfBitF      ar_union0, 29, 1, 1, PrtArChkTil
;        .errnz (MINSYSLADDR - 20000000h)

PrtArChkSys label byte
        JumpIfBitF      ar_union0, 31, 1, 1, PrtArChkTil
        JumpIfBitF      ar_union0, 29, 2, 3, PrtArChkTil
        .errnz (MINSYSLADDR - 60000000h)

; back to system arena iff it is >= 60000000h
                                        ; Jump if system arena
        JumpIfBitF      <ar_hco - aru0>, 0, 16, 0, PrtArInval
                                        ; If zero, field is invalid
        JumpOp          PrtArPtda       ; else must be ptda or null since
                                        ; there's no context record chain

PrtArChkTil label byte
        JumpIfBitF      ar_union0, AR_SELMAPSHIFT, 1, 0, PrtArInval
                                        ; Jump if AR_SELMAP not set

PrtArGDTSel label byte
        OutStr          "  sel="        ; (not hco) & sys & tiled - GDT selector
        JumpOp          PrtArRest

PrtArInval label byte
        OutStr          "     ="        ; (not hco) & sys & not tiled - invalid
        JumpOp          PrtArRest

PrtArPtda label byte
        OutStr          "hptda="        ; (not hco) & (not sys) - PTDA
        JumpOp          PrtArRest

PrtArRest label byte
        OutWordHexPtr   <ar_hco - aru0> ; Output ar_hco/hobptda/sel contents

PrtArCRLF label byte
        OutCrLf
        EndOp

;*      Prints an alias record

PrintAlias      label   byte

AL_ISBUSYSHIFT  equ     0
.errnz  ((1 shl AL_ISBUSYSHIFT) - AL_ISBUSY)

AL_CSALIASSHIFT equ     1
.errnz  ((1 shl AL_CSALIASSHIFT) - AL_CSALIAS)

AL_MEMMAPSHIFT  equ     2
.errnz  ((1 shl AL_MEMMAPSHIFT) - AL_MEMMAP)

        OutBlanks       2
        JumpIfBitF      sal_f, AL_ISBUSYSHIFT, 1, 1, pal00
        OutStr          "palnext="      ; is a free record
        OutDwordHexPtr  sal_har
        OutBlanks       4
        JumpOp          pal50

pal00   label byte
        OutStr          "har="
        OutWordHexPtr   sal_har
        JumpIfBitF      sal_f, AL_CSALIASSHIFT, 1, 1, pal20
                                        ; Jump if AL_CSALIAS set
        OutStr          "  hptda="      ; else vm or memmap alias
        JumpOp          pal40

pal20   label byte
        OutStr          "  cs="
pal40   label byte
        OutWordHexPtr   sal_selcode     ; display hptda or cssel

        JumpIfBitF      sal_f, AL_MEMMAPSHIFT, 1, 1, pal60
        JumpIfBitF      sal_f, AL_CSALIASSHIFT, 1, 1, pal60

;       Is a vm alias (or is a free record).  Display pgoff and flags.

pal50   label byte
        OutStr          "  pgoff="
        OutBitFHexPtr   sal_f,12,<32-12>,5

        OutStr          "  f="
        OutBitFHexPtr   sal_f,0,12,3
        JumpOp          pal90

;       Is a memmap or csalias.  Display dssel, cref
;       (both unused for memmap aliases) and flags.

pal60   label byte
        OutStr          " ds="
        OutWordHexPtr   sal_seldata

        OutStr          " cref="
        OutBitFHexPtr   sal_cref,SAL_ALIASREFSHIFT,<16-SAL_ALIASREFSHIFT>,3

        OutStr          " f="
        OutBitFHexPtr   sal_f,0,SAL_ALIASREFSHIFT,2

pal90   label byte
        OutCrLf
        EndOp

;**** 82818   ***********************************
;*      Prints lock info

PrintLock  label   byte

        OutBlanks 1
        OutStr  "%"
        OutDwordHexAddr li_pvmli

        OutBlanks 1
        OutWordHexAddr li_cs

        OutBlanks 1
        OutDwordHexAddr li_eip

        OutBlanks 1
        OutStr  "%"
        OutDwordHexAddr li_phlock

PrintLock1 label byte

        OutBlanks 1
        OutWordHexAddr li_npages

        OutBlanks 1
        OutStr  "%"
        OutDwordHexAddr li_address

        OutBlanks 1
        OutWordHexAddr li_flg

        OutBlanks 1
        OutWordHexAddr li_hptda

        OutBlanks 1
        OutWordHexAddr li_hob

        OutBlanks 1
        OutWordHexAddr li_sig

        OutBlanks 1
        OutWordHexAddr li_csig
        OutCrLf
        EndOp

;** End 82818   **********************************

;       PrintOwner message strings

Static ptdamsg,         STRING, "ptda "
Static ldtmsg,          STRING, "ldt  "
Static privmsg,         STRING, "priv "
Static mtemsg,          STRING, "mte       "
Static sharemsg,        STRING, "shared    "
Static freemsg,         STRING, "free"
Static UNKNOWNmsg,      STRING, "UNKNOWN"
Static bugmsg,          STRING, "BUG"


?msgno = 0
OwnerMsg macro owner, message, minmax, skipcount
    ifidn <owner>,<skip>
        ?msgno = ?msgno + skipcount
    else
        ifnb <minmax>
            .errnz (owner - minmax)
        endif
        .errnz (?msgno - (owner - VMMINOWNER))
        ?msgno = ?msgno + 1
        ifnb <message>
            Static owner&msg, STRING, message
        endif
    endif
endm

;* Miscellaneous Owners

OwnerMsg OS2DUMPOWNER, "os2dump",VMMINOWNER
OwnerMsg HYBEROWNER, "hybernation"
OwnerMsg DEVKRNLEXITOWNER, "devkrnlexit"
OwnerMsg LDRLIELISTOWNER,"lielist"
OwnerMsg DEMVEROWNER,"demversion"
OwnerMsg VMBMDOWNER,"vmbmapd"
OwnerMsg FSNPIPENPNOWNER,"npipenpn"
OwnerMsg FSNPIPENPOWNER, "npipenp"
OwnerMsg REQPKTTCBOWNER, "reqpkttcb"
OwnerMsg REQPKT2OWNER,   "reqpkt2"
OwnerMsg SPLDEVRMPOWNER, "spldevrmp"
OwnerMsg CHARDEVRMPOWNER,"chardevrmp"
OwnerMsg SYSSEMRMPOWNER, "syssemrmp"
OwnerMsg OS2ROMDATA,     "romdata"
OwnerMsg LDRLIBPATHOWNER,"libpath"
OwnerMsg FSJFNFLAGSOWNER,"jfnflags"
OwnerMsg FSJFNTABLEOWNER,"jfntable"
OwnerMsg PTOUVIRTOWNER,  "ptouvirt "  ; 155843 spacing for .mo display 
OwnerMsg TKR3STACKOWNER, "tkr3stack"
OwnerMsg TKR2STACKOWNER, "tkr2stack"
OwnerMsg TKENVOWNER,     "tkenv"
OwnerMsg TKTIBOWNER,     "tktib"
OwnerMsg REQPKT1OWNER,   "reqpkt1"
OwnerMsg ALLOCPHYSOWNER, "allocphys"
OwnerMsg VMKRHBDONOWNER, "khbdon"
OwnerMsg VMKRHRW1MOWNER, "krhrw1m"
OwnerMsg VMKRHRO1MOWNER, "krhro1m"
OwnerMsg MMPHOWNER,      "mmph"
OwnerMsg PAGEIOOWNER,    "pageio"
OwnerMsg FSRLROWNER,     "fsreclok"
OwnerMsg FSD1OWNER,      "fsd1"
OwnerMsg FSD2OWNER,      "fsd2"
OwnerMsg FSD3OWNER,      "fsd3"
OwnerMsg FSD4OWNER,      "fsd4"
OwnerMsg FSD5OWNER,      "fsd5"
OwnerMsg FSD6OWNER,      "fsd6"
OwnerMsg FSD7OWNER,      "fsd7"
OwnerMsg FSD8OWNER,      "fsd8"
OwnerMsg DD1OWNER,       "dd1"
OwnerMsg DD2OWNER,       "dd2"
OwnerMsg DD3OWNER,       "dd3"
OwnerMsg DD4OWNER,       "dd4"
OwnerMsg DD5OWNER,       "dd5"
OwnerMsg DD6OWNER,       "dd6"
OwnerMsg DD7OWNER,       "dd7"
OwnerMsg DD8OWNER,       "dd8"
OwnerMsg DD9OWNER,       "dd9"
OwnerMsg DD10OWNER,      "dd10"
OwnerMsg DD11OWNER,      "dd11"
OwnerMsg DD12OWNER,      "dd12"
OwnerMsg DD13OWNER,      "dd13"
OwnerMsg DD14OWNER,      "dd14"
OwnerMsg DD15OWNER,      "dd15"
OwnerMsg DD16OWNER,      "dd16"
OwnerMsg FSCMOWNER,      "fsclmap"
OwnerMsg CDSRMPOWNER,    "cdsrmp"
OwnerMsg TOMOWNER,       "tom"
OwnerMsg ABIOSOWNER,     "abios"
OwnerMsg CACHEOWNER,     "cache"
OwnerMsg DBGDCBOWNER,    "dbgdcb"
OwnerMsg DBGKDBTMPOWNER, "dbgkdb"
OwnerMsg DBGWPCBOWNER,   "dbgwpcb"
OwnerMsg DEMFCBSFTOWNER, "demsft"
OwnerMsg DEMFONTOFFOWNER,"demfonto"
OwnerMsg DEMFONTOWNER,   "demfont"
OwnerMsg DEVHLPOWNER,    "devhlp   "    ; spacing for .mo display
OwnerMsg DISCARDOWNER,   "discard"
OwnerMsg DOSHLPOWNER,    "doshlp"
OwnerMsg DYNDTGPTMPOWNER,"dyndtgp"
OwnerMsg DYNDTOOWNER,    "dyndto"
OwnerMsg DYNDTOTMPOWNER, "dyndtot"
OwnerMsg DYNMTEDTLOWNER, "dynmtel"
OwnerMsg EM86MALLOCOWNER,"emalloc"
OwnerMsg EM86TSSOWNER,   "emtss"
OwnerMsg IDDOWNER,       "device"
OwnerMsg INFOSEGOWNER,   "infoseg"
OwnerMsg INITMSGOWNER,   "initmsg"
OwnerMsg INITOWNER,      "init"
OwnerMsg INTDIRQOWNER,   "intdirq"
OwnerMsg INTSTACKOWNER,  "intstack"
OwnerMsg IOPLLISTOWNER,  "iopllist"     ; No longer used....
OwnerMsg KDBALIASOWNER,  "kdbalias"
OwnerMsg KDBSYMOWNER,    "kdbsym"
OwnerMsg KMHOOKOWNER,    "kmhook"
OwnerMsg KSEMOWNER,      "ksem"
OwnerMsg LBDDOWNER,      "lbdd"
OwnerMsg LIDOWNER,       "lid"
OwnerMsg MONITOROWNER,   "monitor"
OwnerMsg MSHAREOWNER,    "mshare  "    ; 155843 spacing for .mo display
OwnerMsg MSHARERMPOWNER, "mshrmp"
OwnerMsg NMIOWNER,       "nmi"
OwnerMsg NPXOWNER,       "npx"
OwnerMsg ORPHANOWNER,    "orphan"
OwnerMsg PROFOWNER,      "prof"
OwnerMsg PTOGDTOWNER,    "ptogdt   "    ; spacing for .mo display
OwnerMsg PTOVIRTOWNER,   "ptovirt  "    ; 155843 spacing for .mo display 
OwnerMsg PUSAGEOWNER,    "puse"
OwnerMsg PUSAGETMPOWNER, "pusetmp"
OwnerMsg PVWOWNER,       "perfview"
OwnerMsg QSCACHETMPOWNER,"qscache"
OwnerMsg RASOWNER,       "ras"
OwnerMsg RSRCBMPOWNER,   "resource"
OwnerMsg SYSSERVOWNER,   "sysserv"
OwnerMsg TIMEROWNER,     "timer"
OwnerMsg TRAPHEOWNER,    "traphe"

;* File System Owners

OwnerMsg FSBUFOWNER,     "fsbuf"
OwnerMsg FSCDEVTMPOWNER, "cdevtmp"
OwnerMsg FSCOWNER,       "fsc"
OwnerMsg FSDPBOWNER,     "dpb"
OwnerMsg FSEATMPOWNER,   "eatmp"
OwnerMsg FSFATSRCHOWNER, "fatsrch"
OwnerMsg FSFNOTIFYGOWNER,"gnotify"
OwnerMsg FSFNOTIFYPOWNER,"pnotify"
OwnerMsg FSHOWNER,       "fsh      "    ; spacing for .mo display
OwnerMsg FSIFSOWNER,     "ifs"
OwnerMsg FSMFSDOWNER,    "mfsd"
OwnerMsg FSMFTOWNER,     "mft"
OwnerMsg FSNPIPEBUFOWNER,"npipebuf"
OwnerMsg FSPIPEOWNER,    "pipe"
OwnerMsg FSSFTOWNER,     "sft"
OwnerMsg FSVPBOWNER,     "vpb"

;* Loader Owners

OwnerMsg LDRCACHEOWNER,  "idcache"
OwnerMsg LDRDLDOWNER,    "ldrdld"
OwnerMsg LDRMKCACHEOWNER,"invalid"
OwnerMsg LDRMTEOWNER,    "ldrmte"
OwnerMsg LDRMTEPATHOWNER,"ldrpath"
OwnerMsg LDRNONRESOWNER, "ldrnres"
OwnerMsg LDRPROT16OWNER, "prot16"

;* Boot Loader and Kernel Owners

OwnerMsg OS2KRNLOWNER,   "os2krnl  "   ; 155843 spacing for .mo display 
OwnerMsg OS2LDROWNER,    "os2ldr   "   ; 155843 spacing for .mo display 
OwnerMsg OS2RIPLOWNER,   "ripl     "   ; 155843 spacing for .mo display 

;* Page Manager Owners

OwnerMsg PGALIASOWNER,   "pgalias"
OwnerMsg PGBUFOWNER,     "pgbuf"
OwnerMsg PGCRPTEOWNER,   "pgcrpte"
OwnerMsg PGDBGALIASOWNER,"dbgalias"
OwnerMsg PGDIROWNER,     "pgdir"
OwnerMsg PGKRNLSTAKOWNER,"pgkstack"
OwnerMsg PGVPOWNER,      "pgvp"
OwnerMsg PGPFOWNER,      "pgpf"
OwnerMsg PGPRTOWNER,     "pgprt"
OwnerMsg PGSYSPTEOWNER,  "pgsyspte"

;* Selector Manager Owners

OwnerMsg SELGDTOWNER,    "gdt"
OwnerMsg SELKHBOWNER,    "selheap"
OwnerMsg SELLDTOWNER,    "ldt"
OwnerMsg SELLOCKOWNER,   "lock"
OwnerMsg SELNOPOWNER,    "selnop"
OwnerMsg SELUVIRTOWNER,  "seluvirt"

;* Semaphore Owners

OwnerMsg SEMMISCOWNER,   "semmisc"
OwnerMsg SEMMUXQOWNER,   "semmuxq"
OwnerMsg SEMOPENQOWNER,  "semopenq"
OwnerMsg SEMSEMRECOWNER, "semrec"
OwnerMsg SEMSTROWNER,    "semstr"
OwnerMsg SEMSTRUCOWNER,  "semstruc"
OwnerMsg SEMTABLEOWNER,  "semtable"

;* Swapper Owners

OwnerMsg SMDFHOWNER,     "smdfh"
OwnerMsg SMSFNOWNER,     "smsfn"
OwnerMsg SMSFOWNER,      "smsf"

;* Tasking Owners

OwnerMsg TKEXITLISTOWNER,"tkextlst"
OwnerMsg TKKMREGOWNER,   "tkkmreg"
OwnerMsg TKLIBIFREEOWNER,"tklibif"
OwnerMsg TKLIBIOWNER,    "tklibi"
OwnerMsg TKPTDAOWNER,    "ptda"
OwnerMsg TKTCBOWNER,     "tcb"
OwnerMsg TKTSDOWNER,     "tsd"

;* VDD, VDH, VDM Owners

OwnerMsg VDDBLOCKHOWNER, "vddblkh"
OwnerMsg VDDBLOCKOWNER,  "vddblk"
OwnerMsg VDDCFGSTROWNER, "vddcfstr"
OwnerMsg VDDCREATMPOWNER,"vddctmp"
OwnerMsg VDDEPOWNER,     "vddep"
OwnerMsg VDDHEAPHOWNER,  "vddheaph"
OwnerMsg VDDHEAPOWNER,   "vddheap"
OwnerMsg VDDHOOKOWNER,   "vddhook"
OwnerMsg VDDLAOWNER,     "vddla"
OwnerMsg VDDLROWNER,     "vddlr"
OwnerMsg VDDMODOWNER,    "vddmod"
OwnerMsg VDDOPENOWNER,   "vddopen"
OwnerMsg VDDPDDEPOWNER,  "vddpddep"
OwnerMsg VDDPROCOWNER,   "vddproc"
OwnerMsg VDDSTROWNER,    "vddstr"
OwnerMsg VDHFHOOKOWNER,  "vdhfhook"
OwnerMsg VDHOWNER,       "vdhalloc"
OwnerMsg VDHSWAPOWNER,   "vdhswap"
OwnerMsg VDMALIASOWNER,  "vdmalias"

;* Virtual Memory Manager Owners

OwnerMsg VMAHOWNER,      "vmah"
OwnerMsg VMALOWNER,      "vmal"
OwnerMsg VMAROWNER,      "vmar"
OwnerMsg VMBMOWNER,      "vmbmap"
OwnerMsg VMCOOWNER,      "vmco"
OwnerMsg VMDEADOWNER,    "vmdead"
OwnerMsg VMHSHOWNER,     "vmhsh"
OwnerMsg VMKRHBOWNER,    "vmkrhb"
OwnerMsg VMKRHFOWNER,    "vmkrhf"
OwnerMsg VMKRHLOWNER,    "vmkrhl"
OwnerMsg VMKRHROOWNER,   "vmkrhro"
OwnerMsg VMKRHRWOWNER,   "vmkrhrw"
OwnerMsg VMKSHDOWNER,    "vmkshd"
OwnerMsg VMKSHROOWNER,   "vmkshro"
OwnerMsg VMKSHRWOWNER,   "vmkshrw"
OwnerMsg VMLLOCKOWNER,   "vmllock"
OwnerMsg VMOBOWNER,      "vmob"
OwnerMsg VMSGSOWNER,     "vmsgs"
OwnerMsg VMTMPBUFOWNER,  "vmbmp16"

OwnerMsg SHRINDRSVD,     "shrind   "    ; 155843 spacing for .mo display 
OwnerMsg GIVESEGOWNER,   "give     "    ; 155843 spacing for .mo display 
OwnerMsg GETSEGOWNER,    "get      "    ; 155843 spacing for .mo display 
OwnerMsg SHRDOWNER,      "giveget  "    ; 155843 spacing for .mo display 

OwnerMsg LDRPRLOBJECT,   "preload", VMMAXOWNER


OwnerMsgPtr macro owner, messageptr, minmax, skipcount
    ifidn <owner>,<skip>
        dw  skipcount dup(dataOFFSET messageptr)
    else
        ifnb <minmax>
            .errnz (owner - minmax)
        endif
        .errnz (($ - OwnerMsgs)/2 - (owner - VMMINOWNER))
        ifb <messageptr>
            dw  dataOFFSET owner&msg
        else
            dw  dataOFFSET messageptr
        endif
    endif
endm

OwnerMsgs label word

OwnerMsgPtr OS2DUMPOWNER,,VMMINOWNER
OwnerMsgPtr HYBEROWNER
OwnerMsgPtr DEVKRNLEXITOWNER
OwnerMsgPtr LDRLIELISTOWNER
OwnerMsgPtr DEMVEROWNER
OwnerMsgPtr VMBMDOWNER
OwnerMsgPtr FSNPIPENPNOWNER
OwnerMsgPtr FSNPIPENPOWNER
OwnerMsgPtr REQPKTTCBOWNER
OwnerMsgPtr REQPKT2OWNER
OwnerMsgPtr SPLDEVRMPOWNER
OwnerMsgPtr CHARDEVRMPOWNER
OwnerMsgPtr SYSSEMRMPOWNER
OwnerMsgPtr OS2ROMDATA
OwnerMsgPtr LDRLIBPATHOWNER
OwnerMsgPtr FSJFNFLAGSOWNER
OwnerMsgPtr FSJFNTABLEOWNER
OwnerMsgPtr PTOUVIRTOWNER
OwnerMsgPtr TKR3STACKOWNER
OwnerMsgPtr TKR2STACKOWNER
OwnerMsgPtr TKENVOWNER
OwnerMsgPtr TKTIBOWNER
OwnerMsgPtr REQPKT1OWNER
OwnerMsgPtr ALLOCPHYSOWNER
OwnerMsgPtr VMKRHBDONOWNER
OwnerMsgPtr VMKRHRW1MOWNER
OwnerMsgPtr VMKRHRO1MOWNER
OwnerMsgPtr MMPHOWNER
OwnerMsgPtr PAGEIOOWNER
OwnerMsgPtr FSRLROWNER
OwnerMsgPtr FSD1OWNER
OwnerMsgPtr FSD2OWNER
OwnerMsgPtr FSD3OWNER
OwnerMsgPtr FSD4OWNER
OwnerMsgPtr FSD5OWNER
OwnerMsgPtr FSD6OWNER
OwnerMsgPtr FSD7OWNER
OwnerMsgPtr FSD8OWNER
OwnerMsgPtr DD1OWNER
OwnerMsgPtr DD2OWNER
OwnerMsgPtr DD3OWNER
OwnerMsgPtr DD4OWNER
OwnerMsgPtr DD5OWNER
OwnerMsgPtr DD6OWNER
OwnerMsgPtr DD7OWNER
OwnerMsgPtr DD8OWNER
OwnerMsgPtr DD9OWNER
OwnerMsgPtr DD10OWNER
OwnerMsgPtr DD11OWNER
OwnerMsgPtr DD12OWNER
OwnerMsgPtr DD13OWNER
OwnerMsgPtr DD14OWNER
OwnerMsgPtr DD15OWNER
OwnerMsgPtr DD16OWNER
OwnerMsgPtr FSCMOWNER

;* Miscellaneous Owners

OwnerMsgPtr CDSRMPOWNER
OwnerMsgPtr TOMOWNER
OwnerMsgPtr ABIOSOWNER
OwnerMsgPtr CACHEOWNER
OwnerMsgPtr DBGDCBOWNER
OwnerMsgPtr DBGKDBTMPOWNER
OwnerMsgPtr DBGWPCBOWNER
OwnerMsgPtr DEMFCBSFTOWNER
OwnerMsgPtr DEMFONTOFFOWNER
OwnerMsgPtr DEMFONTOWNER
OwnerMsgPtr DEVHLPOWNER
OwnerMsgPtr DISCARDOWNER
OwnerMsgPtr DOSHLPOWNER
OwnerMsgPtr DYNDTGPTMPOWNER
OwnerMsgPtr DYNDTOOWNER
OwnerMsgPtr DYNDTOTMPOWNER
OwnerMsgPtr DYNMTEDTLOWNER
OwnerMsgPtr EM86MALLOCOWNER
OwnerMsgPtr EM86TSSOWNER
OwnerMsgPtr IDDOWNER
OwnerMsgPtr INFOSEGOWNER
OwnerMsgPtr INITMSGOWNER
OwnerMsgPtr INITOWNER
OwnerMsgPtr INTDIRQOWNER
OwnerMsgPtr INTSTACKOWNER
OwnerMsgPtr IOPLLISTOWNER       ;No longer used....
OwnerMsgPtr KDBALIASOWNER
OwnerMsgPtr KDBSYMOWNER
OwnerMsgPtr KMHOOKOWNER
OwnerMsgPtr KSEMOWNER
OwnerMsgPtr LBDDOWNER
OwnerMsgPtr LIDOWNER
OwnerMsgPtr MONITOROWNER
OwnerMsgPtr MSHAREOWNER
OwnerMsgPtr MSHARERMPOWNER
OwnerMsgPtr NMIOWNER
OwnerMsgPtr NPXOWNER
OwnerMsgPtr ORPHANOWNER
OwnerMsgPtr PROFOWNER
OwnerMsgPtr PTOGDTOWNER
OwnerMsgPtr PTOVIRTOWNER
OwnerMsgPtr PUSAGEOWNER
OwnerMsgPtr PUSAGETMPOWNER
OwnerMsgPtr PVWOWNER
OwnerMsgPtr QSCACHETMPOWNER
OwnerMsgPtr RASOWNER
OwnerMsgPtr RSRCBMPOWNER
OwnerMsgPtr SYSSERVOWNER
OwnerMsgPtr TIMEROWNER
OwnerMsgPtr TRAPHEOWNER

;* File System Owners

OwnerMsgPtr FSBUFOWNER
OwnerMsgPtr FSCDEVTMPOWNER
OwnerMsgPtr FSCOWNER
OwnerMsgPtr FSDPBOWNER
OwnerMsgPtr FSEATMPOWNER
OwnerMsgPtr FSFATSRCHOWNER
OwnerMsgPtr FSFNOTIFYGOWNER
OwnerMsgPtr FSFNOTIFYPOWNER
OwnerMsgPtr FSHOWNER
OwnerMsgPtr FSIFSOWNER
OwnerMsgPtr FSMFSDOWNER
OwnerMsgPtr FSMFTOWNER
OwnerMsgPtr FSNPIPEBUFOWNER
OwnerMsgPtr FSPIPEOWNER
OwnerMsgPtr FSSFTOWNER
OwnerMsgPtr FSVPBOWNER

;* Loader Owners

OwnerMsgPtr LDRCACHEOWNER
OwnerMsgPtr LDRDLDOWNER
OwnerMsgPtr LDRMKCACHEOWNER
OwnerMsgPtr LDRMTEOWNER
OwnerMsgPtr LDRMTEPATHOWNER
OwnerMsgPtr LDRNONRESOWNER
OwnerMsgPtr LDRPROT16OWNER

;* Boot Loader and Kernel Owners

OwnerMsgPtr OS2KRNLOWNER
OwnerMsgPtr OS2LDROWNER
OwnerMsgPtr OS2RIPLOWNER

;* Page Manager Owners

OwnerMsgPtr PGALIASOWNER
OwnerMsgPtr PGBUFOWNER
OwnerMsgPtr PGCRPTEOWNER
OwnerMsgPtr PGDBGALIASOWNER
OwnerMsgPtr PGDIROWNER
OwnerMsgPtr PGKRNLSTAKOWNER
OwnerMsgPtr PGVPOWNER
OwnerMsgPtr PGPFOWNER
OwnerMsgPtr PGPRTOWNER
OwnerMsgPtr PGSYSPTEOWNER

;* Selector Manager Owners

OwnerMsgPtr SELGDTOWNER
OwnerMsgPtr SELKHBOWNER
OwnerMsgPtr SELLDTOWNER
OwnerMsgPtr SELLOCKOWNER
OwnerMsgPtr SELNOPOWNER
OwnerMsgPtr SELUVIRTOWNER

;* Semaphore Owners

OwnerMsgPtr SEMMISCOWNER
OwnerMsgPtr SEMMUXQOWNER
OwnerMsgPtr SEMOPENQOWNER
OwnerMsgPtr SEMSEMRECOWNER
OwnerMsgPtr SEMSTROWNER
OwnerMsgPtr SEMSTRUCOWNER
OwnerMsgPtr SEMTABLEOWNER

;* Swapper Owners

OwnerMsgPtr SMDFHOWNER
OwnerMsgPtr SMSFNOWNER
OwnerMsgPtr SMSFOWNER

;* Tasking Owners

OwnerMsgPtr TKEXITLISTOWNER
OwnerMsgPtr TKKMREGOWNER
OwnerMsgPtr TKLIBIFREEOWNER
OwnerMsgPtr TKLIBIOWNER
OwnerMsgPtr TKPTDAOWNER
OwnerMsgPtr TKTCBOWNER
OwnerMsgPtr TKTSDOWNER

;* VDD, VDH, VDM Owners

OwnerMsgPtr VDDBLOCKHOWNER
OwnerMsgPtr VDDBLOCKOWNER
OwnerMsgPtr VDDCFGSTROWNER
OwnerMsgPtr VDDCREATMPOWNER
OwnerMsgPtr VDDEPOWNER
OwnerMsgPtr VDDHEAPHOWNER
OwnerMsgPtr VDDHEAPOWNER
OwnerMsgPtr VDDHOOKOWNER
OwnerMsgPtr VDDLAOWNER
OwnerMsgPtr VDDLROWNER
OwnerMsgPtr VDDMODOWNER
OwnerMsgPtr VDDOPENOWNER
OwnerMsgPtr VDDPDDEPOWNER
OwnerMsgPtr VDDPROCOWNER
OwnerMsgPtr VDDSTROWNER
OwnerMsgPtr VDHFHOOKOWNER
OwnerMsgPtr VDHOWNER
OwnerMsgPtr VDHSWAPOWNER
OwnerMsgPtr VDMALIASOWNER

;* Virtual Memory Manager Owners

OwnerMsgPtr VMAHOWNER
OwnerMsgPtr VMALOWNER
OwnerMsgPtr VMAROWNER
OwnerMsgPtr VMBMOWNER
OwnerMsgPtr VMCOOWNER
OwnerMsgPtr VMDEADOWNER
OwnerMsgPtr VMHSHOWNER
OwnerMsgPtr VMKRHBOWNER
OwnerMsgPtr VMKRHFOWNER
OwnerMsgPtr VMKRHLOWNER
OwnerMsgPtr VMKRHROOWNER
OwnerMsgPtr VMKRHRWOWNER
OwnerMsgPtr VMKSHDOWNER
OwnerMsgPtr VMKSHROOWNER
OwnerMsgPtr VMKSHRWOWNER
OwnerMsgPtr VMLLOCKOWNER
OwnerMsgPtr VMOBOWNER
OwnerMsgPtr VMSGSOWNER
OwnerMsgPtr VMTMPBUFOWNER
OwnerMsgPtr SHRINDRSVD
OwnerMsgPtr GIVESEGOWNER
OwnerMsgPtr GETSEGOWNER
OwnerMsgPtr SHRDOWNER
OwnerMsgPtr LDRPRLOBJECT,,VMMAXOWNER


;*      Prints a vmco_s structure

PrintContext    label   byte
        OutStr          "  hconext="
        OutBitFHexPtr   co_fb, 5, 1, 1
        OutWordHexPtr   co_hconext
        OutStr          " hptda="
        OutWordHexPtr   co_hobptda
        OutStr          " f="
        OutByteHexPtr   co_fb
        OutStr          "  pid="
        EndOp

PrintContextFree        label   byte
        OutStr          "  pconext="
        OutDwordHexPtr  0
        EndOp

;*      Prints an inuse pf_s structure

; BUGBUG - the pf_s structure is too much for h2inc and masm to handle

xpf_flags equ   6               ; flags field is in high nibble of this byte
xpf_flink equ   7
xpf_blink equ   4
XPF_FREE equ    40h             ; free flag
PFSIZE  equ     12              ; size of pf structure

PrintBusyPF label   byte
        OutStr          " InUse: pVP="
        OutDwordHexPtr  0
        OutStr          " RefCnt="
        OutWordHexPtr   4
        OutStr          " Flg="
        OutBitFHexPtr   4, 20, 4, 1
        OutStr          " ll="
        OutByteHexPtr   7
        OutStr          " sl="
        OutByteHexPtr   8
        OutStr          " Blk="
        OutBitFHexPtr   8, 12, 20, 5
        OutStr          " Frame="
        EndOp

;*      Prints an idle pf_s structure

PrintIdlePF label byte
        OutStr          " Idle:  pVP="
        OutDwordHexPtr  0
        OutStr          " BLink="
        OutBitFHexPtr   4, 0, 20, 5
        OutStr          " Flg="
        OutBitFHexPtr   4, 20, 4, 1
        OutStr          " FLink="
        OutBitFHexPtr   7, 0, 20, 5
        OutStr          " Blk="
        OutBitFHexPtr   8, 12, 20, 5
        OutStr          " Frame="
        EndOp


;*      Prints a free pf_s structure

PrintFreePF label byte
        OutStr          " Free:              "
        OutStr          " BLink="
        OutBitFHexPtr  4, 0, 20, 5
        OutStr          " Flg="
        OutBitFHexPtr   4, 20, 4, 1
        OutStr          " FLink="
        OutBitFHexPtr   7, 0, 20, 5
        OutStr          " Blk="
        OutBitFHexPtr   8, 12, 20, 5
        OutStr          " Frame="
        EndOp

;*      Prints an inuse vp_s structure

; BUGBUG - the vp structure is a little too much for h2inc and masm.  The
;          following are hack equates for vp fields

xvp_flags       equ     _avp_s_fs
xvp_frame       equ     _avp_s_fs
xvp_semowner    equ     10
ifdef PGSTRICT
VPSIZE          equ     12
else
VPSIZE          equ     10
endif

PrintBusyVP label byte
        OutBitFHexPtr   xvp_frame, 12, 20, 4
        OutStr          " Flg="
        OutBitFHexPtr   xvp_flags, 0, 12, 3
        OutStr          " HobPg="
        OutWordHexPtr   avp_obpg
        OutStr          " Hob="
        OutWordHexPtr   avp_hob
        OutStr          " Ref="
        OutBitFHexPtr   avp_refcount, 0, 12, 3
ifdef PGSTRICT
        OutStr          " Own="
        OutBitFHexPtr   xvp_semowner, 0, 12, 3
endif
        EndOp

;*      Prints a free vp_s structure

PrintFreeVP label byte
        OutStr          " free FLink="
        OutDwordHexPtr  fvp_flink
        OutStr          " BLink="
        OutDwordHexPtr  fvp_blink
        EndOp

DOA_ALLCONTEXTS = 00000001h     ; 'A': all contexts
DOA_MATCH       = 00000002h     ; 'M': dump matching linear address record
DOA_FINDROOT    = 00000004h     ; 'C': walk arena-alias-context-handle chain
DOA_INUSE       = 00000008h     ; 'B': dump in-use records
DOA_FREE        = 00000010h     ; 'F': dump free records
DOA_IDLE        = 00000020h     ; 'I': dump idle records
DOA_NONPSEUDO   = 00000040h     ; 'N': dump normal records
DOA_PSEUDO      = 00000080h     ; 'P': dump pseudo records
DOA_SEM         = 00000100h     ; 'S': dump busy or wanted records
DOA_VERBOSE     = 00000200h     ; 'V': use verbose display
DOA_FLINK       = 00000400h     ; 'L': walk forward links
DOA_BLINK       = 00000800h     ; 'B': walk backward links
DOA_HLINK       = 00001000h     ; 'H': walk hash links
DOA_PHYS        = 00002000h     ; physical address expression given
DOA_LIN         = 00004000h     ; linear address expression given
DOA_DATA        = 00008000h     ; data expression given
DOA_BYTE        = 00010000h     ; count was given in bytes

DOA_ROOT        = 00020000h     ; at the root har


BuildOptions    macro   equname, options
local optval
    optval = 0
    irpc char,<options>
        ifidni <char>,<a>
            optval = optval or DOA_ALLCONTEXTS
        elseifidni <char>,<b>
            optval = optval or DOA_INUSE
        elseifidni <char>,<c>
            optval = optval or DOA_FINDROOT
        elseifidni <char>,<f>
            optval = optval or DOA_FREE
        elseifidni <char>,<h>
            optval = optval or DOA_HLINK
        elseifidni <char>,<i>
            optval = optval or DOA_IDLE
        elseifidni <char>,<l>
            optval = optval or DOA_FLINK
        elseifidni <char>,<m>
            optval = optval or DOA_MATCH
        elseifidni <char>,<n>
            optval = optval or DOA_NONPSEUDO
        elseifidni <char>,<p>
            optval = optval or DOA_PSEUDO
        elseifidni <char>,<r>
            optval = optval or DOA_BLINK
        elseifidni <char>,<s>
            optval = optval or DOA_SEM
        elseifidni <char>,<v>
            optval = optval or DOA_VERBOSE
        endif
    endm
    equname = optval
endm

;       Options table.  Each character that appears below indicates
;       a valid option for the corresponding dump command.
;                       <a b c f h i l m n p r s v>
BuildOptions _ALIAS,    <  b c f                  >
BuildOptions _ARENA,    <a b c f h   l m     r    >
BuildOptions _CONTEXT,  <  b c f                  >
BuildOptions _HEAP,     <                         >
BuildOptions _OBJECT,   <a b c f       m n p   s v>
BuildOptions _PF,       <  b   f   i l       r    >   ; rjm 153574
BuildOptions _VP,       <  b   f     l       r    >
BuildOptions _LOCK,     <            l            >   ;** 82818


;       Default dump counts, starting values and disallowed flags

doa_s struc
        doa_char        db      ?       ; command character
        doa_proc        dw      ?       ; dump procedure
        doa_flags       dd      ?       ; allowed flags
        doa_size        dd      ?       ; structure size
        doa_start       dd      ?       ; default start value
doa_s ends


DOACommands label byte
;   doa_char,           doa_proc,        doa_flags, doa_size,     doa_start
  doa_s <"A", codeOFFSET DOAPrintArena,   _ARENA,   size vmar_s-aru4, 1>
  doa_s <"C", codeOFFSET DOAPrintContext, _CONTEXT, size vmco_s,      1>
  doa_s <"H", codeOFFSET DOAPrintHeap,    _HEAP,    0,                0>
  doa_s <"L", codeOFFSET DOAPrintAlias,   _ALIAS,   size vmsal_s,     1>
  doa_s <"O", codeOFFSET DOAPrintObject,  _OBJECT,  size vmob_s-obu0, 1>
  doa_s <"P", codeOFFSET DOAPrintPF,      _PF,      PFSIZE,           0>
  doa_s <"V", codeOFFSET DOAPrintVP,      _VP,      VPSIZE,           0>
  doa_s <"K", codeOFFSET DOAPrintLock,    _LOCK,    0,                0> ;82818
DOACommandsEnd label byte


;       If an option character matches df_char, set df_flags bits.
;       Cause an error if df_conflict bits are already set.

df_s struc
        df_char         db      ?       ; option character
        df_flag         dd      ?       ; corresponding flag
        df_conflict     dd      ?       ; conflicting flags
df_s ends

DOAOptions label byte
;     df_char, df_flag,         df_conflict
    df_s <"A", DOA_ALLCONTEXTS, DOA_ALLCONTEXTS+DOA_SEM>
    df_s <"B", DOA_INUSE,       DOA_INUSE>
    df_s <"C", DOA_FINDROOT,    DOA_FINDROOT+DOA_FREE>
    df_s <"F", DOA_FREE,        DOA_FINDROOT+DOA_FREE>
    df_s <"H", DOA_HLINK,       DOA_FREE+DOA_FLINK+DOA_BLINK+DOA_HLINK>
    df_s <"I", DOA_IDLE,        DOA_IDLE>
    df_s <"L", DOA_FLINK,       DOA_FLINK+DOA_BLINK+DOA_HLINK>
    df_s <"M", DOA_MATCH,       DOA_MATCH+DOA_SEM>
    df_s <"N", DOA_NONPSEUDO,   DOA_NONPSEUDO+DOA_PSEUDO>
    df_s <"P", DOA_PSEUDO,      DOA_NONPSEUDO+DOA_PSEUDO>
    df_s <"R", DOA_BLINK,       DOA_FLINK+DOA_BLINK+DOA_HLINK>
    df_s <"S", DOA_SEM,         DOA_MATCH+DOA_SEM>
    df_s <"V", DOA_VERBOSE,     DOA_VERBOSE>
DOAOptionsEnd label byte


;       If dfa_mask bits == dfa_value, set dfa_default bits.
;       If dfa_clear bits are clear, set dfa_default bits.

dfauto_s struc
        dfa_mask        dd      ?       ; flags mask
        dfa_value       dd      ?       ; flags value
        dfa_default     dd      ?       ; default flags
dfauto_s ends

DOAAuto label byte
;             dfa_mask, dfa_value, dfa_default
    dfauto_s <DOA_PSEUDO or DOA_NONPSEUDO, 0, DOA_PSEUDO or DOA_NONPSEUDO>
    dfauto_s <DOA_FREE or DOA_INUSE or DOA_IDLE, 0, DOA_INUSE or DOA_IDLE>
    dfauto_s <DOA_MATCH or DOA_ALLCONTEXTS, DOA_ALLCONTEXTS, DOA_MATCH>
DOAAutoEnd label byte

DataSegmentEnd


CodeSegmentStart


;***    DumpMem
;
;       This routine dumps memory management data structures.
;
;       Pseudo code for dumping the chained data structures.  Recursion is
;       flagged by a comment, and indicates one dump routine nesting a call to
;       another (possibly, but not necessarily to a routine already invoked).
;
;       DOAPrintAlias(hal, f)
;           if (f & DOA_FINDROOT)
;               DOAPrintArena(hal.har, DOA_FINDROOT)    ; recurse
;           else
;               print(hal)
;
;       DOAPrintArena(har, f)
;           if (f & DOA_FINDROOT)
;               DOAPrintObject(har.hob, DOA_FINDROOT)   ; recurse
;           else
;               print(har)
;
;       DOAPrintObject(hob, f)
;           if (f & DOA_FINDROOT)
;               hal = hco = 0
;               har = hob.har
;               f2 = DOA_ROOT
;               while (har)
;                   hcotmp, hobtmp, hal, har = DOAPrintArena(har, f2) ; recurse
;                   f2 = 0
;                   if (hcotmp)
;                       hco = hcotmp
;                   if (hobtmp)
;                       hob = hobtmp
;                   if (hal)
;                       DOAPrintAlias(hal, 0)           ; recurse
;               while (hob)
;                   hob = DOAPrintObject(hob, 0)        ; recurse
;               while (hco)
;                   hco = DOAPrintContext(hco, 0)       ; recurse
;           else
;               print(hob)
;
;       ENTRY   NONE
;       EXIT    NONE
;       USES    ALL

DefProc DumpMem, NEAR, PUBLIC
    assumeDATA <ds, es, ss>
        xor     ebx,ebx                 ; clear flags
        Pcall   PeekChr                 ; (AL) = character
        mov     di,dataOFFSET DOACommands
        jz      short dme00
        cmp     al," "
        jnz     short dme10
dme00:  mov     al,"A"                  ; default to ".mamc cs:eip"
        mov     ebx,DOA_FINDROOT+DOA_MATCH

dme10:  cmp     [di].doa_char,al
        jz      short dme20
        add     di,size doa_s
        cmp     di,dataOFFSET DOACommandsEnd
        jnz     short dme10

        putstr  <"Invalid command">
        Jump    CmdBreak

dme20:  or      ebx,ebx                 ; default options?
        jnz     short dme40             ; jmp if default options already set
        Pcall   SkipB                   ; eat the character in the input buffer

;       (DI) = pointer to doa_s structure

        or      ebx,ebx                 ; default options?
        jnz     short dme40             ; jmp if options already set
        Pcall   DOAParseOptions         ; (bx) = display flags

;       (EBX) = display flags
;       (DI) = pointer to doa_s structure

dme40:  Pcall   DOAParseRange           ; (ecx) = count, (edx) = record number
        or      ecx,ecx
        jz      short dmex
        xor     si,si                   ; force the header to be printed

;       Display the object/arena records or page/swap frames
;
;       (EAX) = match address if DOA_MATCH set in (BX)
;       (EBX) = display flags
;       (ECX) = number of entries to print
;       (EDX) = starting value
;       (SI)  = number of lines on this page counter
;       (DI)  = pointer to doa_s structure

        call    [di].doa_proc           ; call worker
dmex:
EndProc


;***    DOAParseOptions
;
;       Parse the dump memory data structure options.
;
;       ENTRY   (DI) = doa_s structure pointer
;       EXIT    (EBX) = display flags
;       USES    AX, EBX, SI, Flags

DefProc DOAParseOptions, NEAR, LOCAL
    assumeDATA <ds, es, ss>
        xor     ebx,ebx
dpo00:  Pcall   PeekChr                 ; (AL) = character
        jz      short dpo50
        mov     si,dataOFFSET DOAOptions
        cmp     al,"A"
        jb      short dpo50
        cmp     al,"Z"
        ja      short dpo50
dpo10:  cmp     [si].df_char,al         ; find a valid option char?
        jz      short dpo20
        add     si,size df_s
        cmp     si,dataOFFSET DOAOptionsEnd ; more option chars left?
        jnz     short dpo10             ; jmp if so, skip to next
        putstr  <"Unknown option">
        jmp     short dpo27

dpo20:  test    ebx,[si].df_conflict    ; conflict?
        jnz     short dpo25             ; if so, cause error
        mov     eax,[si].df_flag        ; (EAX) = corresponding flag
        test    eax,[di].doa_flags      ; valid option?
        jz      short dpo26
        or      ebx,eax                 ; else set corresponding flags,
        Pcall   SkipB                   ; eat the character in the input buffer
        jmp     short dpo00             ; and restart the scan

dpo25:  putstr  <"Conflicting option">
        jmp     short dpo27

dpo26:  putstr  <"Invalid option">
dpo27:  Jump    CmdBreak

dpo50:  mov     si,dataOFFSET DOAAuto
dpo60:  mov     ecx,ebx
        and     ecx,[si].dfa_mask       ; default bits need to be set?
        cmp     ecx,[si].dfa_value
        jnz     short dpo80             ; jmp if not
        or      ebx,[si].dfa_default    ; else set defaults
dpo80:  add     si,size dfauto_s
        cmp     si,dataOFFSET DOAAutoEnd ; at end of list?
        jnz     short dpo60
EndProc


;***    DOAParseRange
;
;       Parse the dump memory data structure range.
;
;       ENTRY   (EBX) = display flags
;               (DI) = doa_s structure pointer
;       EXIT    (EAX) = linear address to match
;               (EBX) = modified display flags
;               (ECX) = number of records to print
;               (EDX) = starting record number
;       USES    EAX, BX, ECX, EDX, ESI, Flags

DefProc DOAParseRange, NEAR, LOCAL
    assumeDATA <ds, es, ss>
    LocVar dpr_Addr, <size AddrS>
BeginProc
        mov     cx,1
        test    ebx,DOA_FLINK or DOA_BLINK or DOA_HLINK
        jz      short dpr00
        mov     cx,-1
dpr00:  Pcall   ScanP
        lea     si,[dpr_Addr]           ; (SI) = AddrS structure
        jnz     short dpr10             ; jmp if command line not empty
        mov     ax,dataOFFSET DisAddr   ; (AX) = cs:eip AddrS structure
        test    ebx,DOA_MATCH
        jnz     short dpr20             ; jmp if default cs:eip
        jmp     dpr70                   ; jmp if no default

dpr10:  Pcall   FillDataAddr, <si, 0, 0>
        mov     ax,si                   ; (AX) = AddrS structure

;       ('c'set,CX=No.bytes/'c'clear,CX=No.objects) == EvalRange(def,new,cnt)

dpr20:  Pcall   EvalRange, <ax, si, cx>
        movsx   ecx,cx
        jnc     short dpr30
        or      ebx,DOA_BYTE            ; indicate byte range

dpr30:  mov     al,[dpr_Addr].AddrType  ; (AL) = address type
        mov     edx,[dpr_Addr].AddrOff  ; (EDX) = start address/object number
        xor     esi,esi
        cmp     al,EXPR_TYPE_DATA
        jz      short dpr40

        mov     esi,DOA_PHYS
        cmp     al,EXPR_TYPE_PHY
        jz      short dpr40

        mov     esi,DOA_LIN
        cmp     al,EXPR_TYPE_LIN
        jz      short dpr40

        push    ebx
        push    ecx
        lea     bx,[dpr_Addr]           ; (bx) = address structure
        xor     cx,cx                   ; (cx) = no limit check
        Pcall   AddrToLin               ; (ax:dx)=lin = AddrToLin(bx=addr,cx=0)
        pop     ecx
        pop     ebx
        jnc     short dpr38

dpre:   putstr  <"Invalid expression">
        Jump    CmdBreak

dpr38:  xchg    dx,ax                   ; (EDX) = start address
        shl     edx,16
        mov     dx,ax
dpr40:  or      ebx,esi                 ; set expression type flag

        test    ebx,DOA_MATCH           ; if matching laddr
        jz      short dpr80
        test    ebx,DOA_BYTE or DOA_DATA ; and byte range or data expr. given
        jnz     short dpre
        cmp     ecx,1                   ; or any count given
        jnz     short dpre              ; cause an error
        and     ebx,not DOA_LIN         ; to avoid problems later
        mov     eax,edx                 ; (EAX) = match addr

;       Set the defaults to examine every record.
;
;       (EAX) = match address if DOA_MATCH set in (BX)
;       (EBX) = display flags
;       (DI)  = doa_s structure pointer

dpr70:  mov     edx,[di].doa_start      ; start at beginning
        mov     ecx,-1                  ; display all the entries
        jmp     short dprx

dpr80:  test    ebx,DOA_PHYS            ; if not matching, and paddr given
        jnz     short dpre              ; cause an error
        mov     esi,ebx
        and     esi,DOA_LIN or DOA_BYTE ; if not matching,
        cmp     esi,DOA_LIN or DOA_BYTE ; and laddr and byte range given
        jnz     short dpr90
        push    edx
        xor     edx,edx                 ; then convert bytes to object count
        mov     eax,ecx                 ; (edx:eax) = (ecx) + size - 1
        add     eax,[di].doa_size
        dec     eax
        idiv    [di].doa_size           ; (eax) = (edx:eax)/size
        mov     ecx,eax                 ; (ecx) = object count
        pop     edx

;       (BX)  = display flags
;       (ECX) = object count
;       (EDX) = start record number
;       (DI)  = doa_s structure pointer

dpr90:  cmp     ecx,1
        jnz     short dprx
        or      ebx,DOA_NONPSEUDO+DOA_PSEUDO+DOA_INUSE+DOA_FREE
dprx:
EndProc


;***    DOAPrintArena
;
;       The routine dumps the arena record(s) in the specified range
;
;       ENTRY   (EAX) = match address if DOA_MATCH set in (EBX)
;               (EBX)  = display flags
;               (ECX) = number of records to display
;               (EDX) = start handle
;               (SI)  = number of lines printed
;       EXIT    (EAX) = hob from non-alias arena record
;               (EBX) = hco from arena record
;               (CX)  = 0 if none printed
;               (EDX) = next handle
;               (SI)  = number of lines printed
;               (EDI) = hal from arena record
;       USES    ALL

DefProc DOAPrintArena, NEAR, LOCAL
    assumeDATA <ds, es, ss>
    LocVar dar_matchaddr, DWORD
    LocVar dar_flags, DWORD
    LocVar dar_count, DWORD
    LocVar dar_har, DWORD
    LocVar dar_cline, WORD
    LocVar dar_hobptda, WORD
    LocVar dar_harlink, DWORD
    LocVar dar_fprint, WORD
    LocVar dar_harnext, DWORD
    LocVar dar_hobchain, DWORD
    LocVar dar_hcochain, DWORD
    LocVar dar_halchain, DWORD
    LocVar dar_addr, <size AddrS>
BeginProc
        DOAENTRY <"arena">
        mov     [dar_matchaddr],eax
        mov     [dar_flags],ebx
        mov     [dar_count],ecx
        mov     [dar_har],edx
        mov     [dar_cline],si
        xor     eax,eax
        mov     [dar_harlink],eax
        mov     [dar_fprint],ax
        mov     [dar_hobchain],eax
        mov     [dar_hcochain],eax
        mov     [dar_halchain],eax
        mov     [dar_hobptda],ax
        and     ebx,DOA_MATCH or DOA_ALLCONTEXTS
        cmp     ebx,DOA_MATCH
        jnz     short dar10
        cmp     [dar_matchaddr],MINSYSLADDR
        jae     short dar10
        Pcall   DebGetCurrHobPTDA
        jc      short dar10
        mov     [dar_hobptda],dx

dar10:  lea     bx,[dar_addr]
        mov     ecx,[dar_flags]
        and     cx,DOA_LIN
        .errnz  (DOA_LIN and 0ffff0000h)
        mov     edx,[dar_har]
        Pcall   GetArenaTable
        jc      short dar20

        mov     [dar_har],edx
        inc     edx
        mov     [dar_harnext],edx
        mov     dx,size vmar_s - aru4
        Pcall   GetCache                ; (DI) = cache buffer

;       We get here with carry set when the arena data is past the end
;       of the arena record array or when a page fault is encountered.
;       This means we've finished dumping the arena - So clean up and exit.

dar20:  cmc
        jnc     darx                    ; finished - (end of table reached)

        mov     eax,dword ptr [di].ar_union0 ; (EAX) = ar_f + ar_ipg
        test    ax,AR_INUSE             ; ar_f
        jz      dar30                   ; jmp if arena record is free

        test    [dar_flags],DOA_MATCH
        jz      short dar25             ; jmp if should not address match

;       We are displaying only those arena records that enclose the linear
;       address specified.  If the arena record is in the private arena,
;       and if we're supposed to be matching context, and if the context
;       does not match, skip the arena record.
;
;       if (matchaddr NOT within arena record)
;           go skip record
;       if (matchaddr in system arena)
;           go display record
;       if (arena record in shared arena & has shared contents) (if AR_HCO set)
;           go display record
;       if (arena record in shared arena & private contents) (if ar_hobptda 0)
;           go display record
;       if (we're ignoring context) (if LocalVar hobptda is 0)
;           go display record
;       if (context matches) (if LocalVar hobptda matches ar_hobptda)
;           go display record
;       go skip record

        and     eax,not (PAGESIZE - 1)  ; turn off flag bits
        cmp     [dar_matchaddr],eax
        jb      dar80                   ; jmp if address is below arena entry
        shr     eax,PAGESHIFT
;;;;;;; add     eax,[di].ar_cpg         ; (EAX) += ar_cpg
        mov     ecx,dword ptr [di].ar_union5 ;
        and     ecx,_ar_cpg                  ; EAX += ar_cpg
        add     eax,ecx                      ;
        shl     eax,PAGESHIFT
        cmp     [dar_matchaddr],eax
        jae     dar80                   ; jmp if address is above arena entry
        cmp     [dar_matchaddr],MINSYSLADDR
        jae     short dar27             ; match all if system arena
        test    word ptr [di].ar_union0,AR_HCO           ; ar_f
        jnz     short dar27             ; or if shared content in shared arena
        cmp     word ptr [di].ar_hco,0 ; compare to ar_hobptda
        jz      short dar27             ; allow match if shared arena
        mov     cx,[dar_hobptda]        ; (cx) = hobptda
        jcxz    short dar27             ; allow match if invalid hobptda
        cmp     word ptr [di].ar_hco,cx ; compare to ar_hobptda
        jz      short dar27             ; go display the chain
        jmp     dar80                   ; jmp if hobptda doesn't match

dar25:  test    [dar_flags],DOA_INUSE
        jz      dar80                   ; jmp if should skip busy records
dar27:  test    [dar_flags],DOA_FINDROOT
        jz      short dar40             ; jmp if should print without chain

        movzx   edx,word ptr [di-aru0].ar_hob   ; (edx) = ar_hob
        or      edx,edx
        jz      dar80
        mov     ebx,DOA_INUSE+DOA_NONPSEUDO+DOA_PSEUDO+DOA_DATA+DOA_FINDROOT
        mov     ecx,1
        xor     si,si
        Pcall   DOAPrintObject          ; recurse to find and print from root
        jmp     dar80

dar30:  test    [dar_flags],DOA_FREE
        jz      dar80                   ; jmp if should not dump free records
        test    [dar_flags],DOA_MATCH
        jnz     dar80                   ; jmp if should address match

;       We've decided to print this arena record.  If we're printing
;       the root arena record of a chain, lead off with an asterisk.

dar40:  cmp     [dar_cline],0
        jnz     short dar48

        mov     al," "
        test    [dar_flags],DOA_ROOT    ; dumping chain root?
        jz      short dar45
        Pcall   crlf
        mov     al,"*"
dar45:  Pcall   putchar
        putstr  <"har     par      cpg        va    flg next prev link hash hob   hal",CR,LF>
        mov     [dar_cline],LINES_PER_PAGE ; number lines per page

;       Save away appropriate fields.

dar48:  dec     [dar_cline]             ; one more line printed
        mov     [dar_fprint],1
        movzx   edx,[di-aru0].ar_harlink ; (edx) = ar_harlink
        mov     [dar_harlink],edx
        test    [dar_flags],DOA_FLINK or DOA_BLINK or DOA_HLINK
        jz      short dar50
        movzx   edx,[di-aru0].ar_harhash ; (EDX) = ar_harhash
        test    [dar_flags],DOA_HLINK
        jnz     short dar49
        movzx   edx,[di-aru0].ar_harnext ; (EDX) = ar_harnext
        test    [dar_flags],DOA_FLINK
        jnz     short dar49
        movzx   edx,[di-aru0].ar_harprev ; (EDX) = ar_harprev
dar49:  mov     [dar_harnext],edx

;       Save the hco if the AR_HCO flags bit is set.
;       Save the hal if non-zero.
;       Save the hob if not an alias record (if the hal is zero).

dar50:  test    word ptr [di].ar_union0,AR_HCO           ; ar_f
        jz      short dar51
;;;;;;; movzx   edx,word ptr [di-aru0].ar_hco   ; (edx) = ar_hco
        movzx   edx,word ptr [di].ar_union5.HighWord
        and     dx,AR_HCOH shl 4
        shl     edx, 12
        mov     dx,word ptr [di-aru0].ar_hco
        mov     [dar_hcochain],edx
dar51:  movzx   edx,word ptr [di-aru4].ar_hal   ; (edx) = ar_hal
        or      edx,edx
        jz      short dar52
        mov     [dar_halchain],edx
        jmp     short dar54

dar52:  movzx   edx,word ptr [di-aru0].ar_hob   ; (edx) = ar_hob
        mov     [dar_hobchain],edx

;       Dump the arena record.

dar54:  Pcall   blank
        mov     edx,[dar_har]
        Pcall   out16                   ; print handle number
        putstr  <" %">
        mov     dx,[dar_addr].AddrOff.HighWord
        Pcall   out16                   ; print high address
        mov     dx,[dar_addr].AddrOff.LowWord
        Pcall   out16                   ; print low address
        mov     si,dataOFFSET PrintArena
        Pcall   OpInterpret

;       We're finished processing one record.  Loop if counter > 1.

dar80:  and     [dar_flags],not DOA_LIN
        mov     edx,[dar_harnext]
        mov     [dar_har],edx           ; set next handle
        dec     [dar_count]
        jnz     dar10                   ; loop

darx:   mov     eax,[dar_hobchain]
        mov     ebx,[dar_hcochain]
        mov     cx,[dar_fprint]
        mov     edx,[dar_harlink]
        mov     si,[dar_cline]
        mov     edi,[dar_halchain]
EndProc


;***    DOAPrintObject
;
;       The routine dumps the object(s) in the specified range
;
;       ENTRY   (EAX) = match address if DOA_MATCH set in (EBX)
;               (EBX)  = display flags
;               (ECX) = number of records to display
;               (EDX) = start handle
;               (SI)  = number of lines printed
;       EXIT    (EDX) = next handle
;               (SI)  = number of lines printed
;       USES    ALL

DefProc DOAPrintObject, NEAR, LOCAL
    assumeDATA <ds, es, ss>
    LocVar dob_matchaddr, DWORD
    LocVar dob_flags, DWORD
    LocVar dob_count, DWORD
    LocVar dob_hob, DWORD
    LocVar dob_cline, WORD
    LocVar dob_hobnext, DWORD
    LocVar dob_hobchain, DWORD
    LocVar dob_hcochain, DWORD
    LocVar dob_addr, <size AddrS>
    LocVar dob_cllock, BYTE            ;155843 need to save these for .MK
    LocVar dob_cslock, BYTE            ;155843 need to save these for .MK
BeginProc
        DOAENTRY <"object">
        mov     [dob_matchaddr],eax
        mov     [dob_flags],ebx
        mov     [dob_count],ecx
        mov     [dob_hob],edx
        mov     [dob_cline],si
        mov     [dob_hobnext],0
        mov     [dob_cllock],0         ;155843
        mov     [dob_cslock],0         ;155843

dob00:  lea     bx,[dob_addr]
        mov     ecx,[dob_flags]
        and     cx,DOA_LIN
        .errnz  (DOA_LIN and 0ffff0000h)
        mov     edx,[dob_hob]
        Pcall   GetObjectTable
        jc      short dob10

        mov     [dob_hob],edx
        mov     dx,size vmob_s - obu0
        Pcall   GetCache                ; (DI) = cache buffer
        jnc     short dob20             ; jmp if valid normal handle

;       We get here with carry set when the handle data is past the end
;       of the handle array or when a page fault is encountered.  This
;       means we're dumping system owners or we've finished dumping all
;       the handles - clean up and exit in the latter case.

dob10:  mov     esi,[dob_hob]
        cmp     si,VMMAXOWNER           ; highest simple owner equate
        ja      dobx                    ; exit
        mov     dx,si
        sub     si,VMMINOWNER           ; lowest simple owner equate
        jb      dobx                    ; exit
        shl     si,1
        Pcall   out16                   ; print owner value in dx
        Pcall   blank
        mov     dx,[OwnerMsgs+si]
        Pcall   rprbuf
        Pcall   crlf                    ;82818
        jmp     dob80                   ;82818

dob20:  cmp     [di-obu0].ob_hobowner,0 ; is the handle free?
        jz      dob44                   ; jmp if free

        mov     al,[di-obu0].ob_cllock  ;155843
        mov     [dob_cllock],al         ;155843
        mov     al,[di-obu0].ob_cslock  ;155843
        mov     [dob_cslock],al         ;155843

        mov     ax,[di-obu0].ob_fs      ; (AX) = flags
        test    [dob_flags],DOA_MATCH   ; display only if address matches?
        jz      short dob22
        test    ax,OB_PSEUDO            ; only valid for pseudo objects
        jz      dob80                   ; jmp if not a pseudo object
        mov     eax,[di-obu0].ob_va
        cmp     [dob_matchaddr],eax
        jnz     dob80                   ; jmp if no match
        jmp     dob46                   ; else matches; jmp to display record

dob22:  test    [dob_flags],DOA_SEM     ; display only if busy or wanted?
        jz      short dob24

        test    ax,OB_LOCKWAIT
        jnz     dob46
        cmp     [di-obu0].ob_bsemcnt,0
        jnz     dob46
        cmp     [di-obu0].ob_wsemowner,0
        jnz     dob46
        jmp     dob80

dob24:  test    [dob_flags],DOA_INUSE   ; display in-use object records?
        jz      dob80                   ; jmp if not
        test    ax,OB_PSEUDO            ; is it a pseudo object?
        jz      short dob26             ; jmp if not a pseudo object
        test    [dob_flags],DOA_PSEUDO  ; display only if pseudo object?
        jnz     dob46
        jmp     dob80

dob26:  test    [dob_flags],DOA_NONPSEUDO ; display only if non-psuedo?
        jz      dob80
        test    [dob_flags],DOA_FINDROOT  ; dump chain from the root?
        jz      dob46

        xor     eax,eax
        mov     [dob_hobchain],eax
        mov     [dob_hcochain],eax

        mov     ebx,DOA_INUSE+DOA_DATA+DOA_ROOT
        movzx   edx,word ptr [di].ob_har ; (EDX) = arena record handle
        xor     si,si
dob28:  or      edx,edx
        jz      short dob36
        mov     ecx,1
        Pcall   DOAPrintArena           ; recurse to print 1 arena record chain
        jc      short dob36

        or      ebx,ebx                 ; store hco chain if non-zero
        jz      short dob30
        mov     [dob_hcochain],ebx
dob30:  or      eax,eax                 ; store hob chain if non-zero
        jz      short dob32
        mov     [dob_hobchain],eax

;       Recurse to print the alias record, if any.
;       If the hal field was non-zero, print the alias.

dob32:  or      edi,edi
        jz      short dob34
        mov     [dob_cline],0
        push    edx                     ; save next har
        mov     ebx,DOA_INUSE+DOA_DATA
        mov     ecx,1
        mov     edx,edi                 ; (edx) = hal
        xor     si,si
        Pcall   DOAPrintAlias           ; recurse to print one alias record
        pop     edx                     ; restore next har
        xor     si,si
dob34:  mov     ebx,DOA_INUSE+DOA_DATA
        jmp     short dob28

;       Arena and alias record have all been dumped.
;       Dump the object record and context record lists, if any.
;
;       Recurse to print a list of object records.

dob36:  mov     edx,[dob_hobchain]      ; (edx) = hob chain
        xor     si,si
dob38:  or      edx,edx
        jz      short dob40
        mov     ebx,DOA_INUSE+DOA_NONPSEUDO+DOA_PSEUDO+DOA_DATA
        mov     ecx,1
        Pcall   DOAPrintObject          ; recurse to print one object record
        jnc     short dob38

;       Recurse to print a list of context records.

dob40:  mov     edx,[dob_hcochain]      ; (edx) = hco chain
        xor     si,si
dob42:  or      edx,edx
        jz      dob80
        mov     ebx,DOA_INUSE+DOA_DATA
        mov     ecx,1
        Pcall   DOAPrintContext         ; recurse to print one context record
        jnc     short dob42
        jmp     dob80

dob44:  test    [dob_flags],DOA_FREE    ; display free object records?
        jz      dob80                   ; jmp if not

dob46:  cmp     [dob_cline],0
        jnz     short dob60

        putstr  <" hob   ">
        test    [dob_flags],DOA_VERBOSE
        jz      short dob48
        putstr  <"  pob     ">
dob48:  cmp     [di-obu0].ob_hobowner,0 ; is the handle free?
        jz      short dob50
        test    [di-obu0].ob_fs,OB_PSEUDO
        jnz     short dob50
        putstr  <"har hobnxt">
        jmp     short dob55

dob50:  putstr  <"    va    ">
dob55:  putstr  <" flgs own  hmte  sown,cnt lt st xf", CR, LF>
        mov     [dob_cline],LINES_PER_PAGE ; number lines per page

dob60:  dec     [dob_cline]             ; one more line printed
        mov     al," "
        test    [dob_flags],DOA_FINDROOT        ; dump chain?
        jz      short dob62
        mov     al,"*"
dob62:  Pcall   putchar
        mov     edx,[dob_hob]
        Pcall   out16                   ; print handle number
        test    [dob_flags],DOA_VERBOSE
        jz      short dob65
        putstr  <" %">
        mov     dx,[dob_addr].AddrOff.HighWord
        Pcall   out16                   ; print high address
        mov     dx,[dob_addr].AddrOff.LowWord
        Pcall   out16                   ; print low address
dob65:  push    di                      ;82818
        mov     si,dataOFFSET PrintObject
        Pcall   OpInterpret
        movzx   edx,word ptr [di].ob_hobnext
        mov     [dob_hobnext],edx
        test    [dob_flags],DOA_VERBOSE
        jnz     short dob66             ;82818

        mov     edx,[dob_hob]
        Pcall   PrintOwner

;155843 PrintOwner may call PrintMTE which reuses the cache for Module
;       name. So we use the saved lock counts in local vars
dob66:  Pcall   crlf                    ;82818
        pop     di                      ;82818
;        cmp     [di-obu0].ob_cllock,0   ;82818  1555843
;        jnz     short dob67             ;82818  1555843
;        cmp     [di-obu0].ob_cslock,0   ;82818  1555843
;        jz      short dob80             ;82818  1555843
        cmp     [dob_cllock],0           ; 155843
        jnz     short dob67              ; 155843
        cmp     [dob_cslock],0           ; 155843
        jz      short dob80              ; 155843
dob67:  xor     ebx,ebx                 ;82818
        mov     edx,[dob_hob]           ;82818
        xor     si,si                   ;82818
        Pcall   DOAPrintLock            ;82818
dob80:  and     [dob_flags],not DOA_LIN
        inc     [dob_hob]               ; next handle
        dec     [dob_count]
        jnz     dob00                   ; loop
dobx:   clc
        mov     edx,[dob_hobnext]
        mov     si,[dob_cline]
EndProc


;***    DOAPrintAlias
;
;       The routine dumps the alias record(s) in the specified range
;
;       ENTRY   (EAX) = match address if DOA_MATCH set in (EBX)
;               (EBX)  = display flags
;               (ECX) = number of records to display
;               (EDX) = start handle
;               (SI)  = number of lines printed
;       EXIT    (CX)  = 0 if none printed
;       USES    ALL

DefProc DOAPrintAlias, NEAR, LOCAL
    assumeDATA <ds, es, ss>
    LocVar dal_flags, DWORD
    LocVar dal_count, DWORD
    LocVar dal_hal, DWORD
    LocVar dal_hallink, DWORD
    LocVar dal_fprint, WORD
    LocVar dal_halnext, DWORD
    LocVar dal_addr, <size AddrS>
BeginProc
        DOAENTRY <"alias">
        mov     [dal_flags],ebx
        mov     [dal_count],ecx
        mov     [dal_hal],edx
        mov     [dal_hallink],0
        mov     [dal_fprint],0

dal00:  lea     bx,[dal_addr]
        mov     ecx,[dal_flags]
        and     cx,DOA_LIN
        .errnz  (DOA_LIN and 0ffff0000h)
        mov     edx,[dal_hal]
        Pcall   GetAliasTable
        jc      short dal20

        mov     [dal_hal],edx
        inc     edx
        mov     [dal_halnext],edx
        mov     dx,size vmsal_s
        Pcall   GetCache                ; (DI) = cache buffer

;       We get here with carry set when the alias data is past the end
;       of the alias record array or when a page fault is encountered.
;       This means we've finished dumping the array - So clean up and exit.

dal20:  cmc
        jnc     dalx                    ; finished - (end of table reached)

        mov     ax,word ptr [di].sal_f  ; (ax) = sal_f
        test    ax,AL_ISBUSY
        jz      short dal30             ; jmp if alias record is free
        test    [dal_flags],DOA_FINDROOT
        jz      short dal25             ; jmp if should print

        xor     cx,cx                   ; else find root and print chain
        movzx   edx,[di].sal_har        ; (edx) = sal_har
        or      edx,edx
        jz      short dal80
        mov     ebx,DOA_INUSE+DOA_DATA+DOA_FINDROOT
        mov     ecx,1
        xor     si,si
        Pcall   DOAPrintArena           ; recurse to find and print from root
        jmp     short dal80

dal25:  test    [dal_flags],DOA_INUSE
        jnz     short dal40             ; jmp if should dump busy records
        jmp     short dal80

dal30:  test    [dal_flags],DOA_FREE
        jz      short dal80             ; jmp if should not dump free records

dal40:  mov     [dal_fprint],1
        putstr  <" hal=">
        mov     edx,[dal_hal]
        Pcall   out16                   ; print handle number
        putstr  <" pal=%">
        mov     dx,[dal_addr].AddrOff.HighWord
        Pcall   out16                   ; print high address
        mov     dx,[dal_addr].AddrOff.LowWord
        Pcall   out16                   ; print low address
        mov     si,dataOFFSET PrintAlias
        Pcall   OpInterpret

dal80:  and     [dal_flags],not DOA_LIN
        mov     edx,[dal_halnext]
        mov     [dal_hal],edx           ; set next handle
        dec     [dal_count]
        jnz     dal00                   ; loop

dalx:   mov     cx,[dal_fprint]
EndProc

;*** 82818 ***********************************************
;***    DOAPrintLock
;
;       The routine dumps the locks in the specified range
;
;       ENTRY   (EBX) = display flags
;               (ECX) = number of records to display
;               (EDX) = start handle
;               (SI)  = number of lines printed
;       EXIT    None
;       USES    ALL

DefProc DOAPrintLock, NEAR, PUBLIC
    assumeDATA <ds, es, ss>
    LocVar dpl_flags, DWORD
    LocVar dpl_count, DWORD
    LocVar dpl_target_hob, WORD
    LocVar dpl_curr_hob, WORD
    LocVar dpl_cline, WORD
    LocVar dpl_pVMLICurr, DWORD
    LocVar dpl_li_pvmli, DWORD
    LocVar dpl_li_cs, WORD
    LocVar dpl_li_eip, DWORD
    LocVar dpl_li_phlock, DWORD
    LocVar dpl_li_address, DWORD
    LocVar dpl_li_flg, WORD
    LocVar dpl_li_hptda, WORD
    LocVar dpl_li_npages, WORD
    LocVar dpl_li_hob, WORD
    LocVar dpl_li_sig, WORD
    LocVar dpl_li_csig, WORD
    LocVar dpl_li_address1, DWORD
    LocVar dpl_li_flg1, WORD
    LocVar dpl_li_hptda1, WORD
    LocVar dpl_li_npages1, WORD
    LocVar dpl_li_hob1, WORD
    LocVar dpl_li_sig1, WORD
    LocVar dpl_li_csig1, WORD
    LocVar dpl_diff, WORD
BeginProc
        DOAENTRY <"lock">
        mov     [dpl_flags],ebx
        mov     [dpl_count],ecx
        mov     [dpl_target_hob],dx
        mov     [dpl_cline],si
        mov     [dpl_diff],0

        mov     ebx,FLAToffset _pVMLIHead
        push    ds                      ; save ds
        FlatContext <ds>,ax             ; DS = Flat
dpl00:  mov     ebx,[ebx].vmli_next
        or      ebx,ebx
        jz      short dpl05
        mov     [ebx].vmli_flags,0
        jmp     dpl00
dpl05:  pop     ds                      ; restore ds
     assumeDATA ds                      ;

        mov     ebx,FLAToffset _pVMLIHead
        mov     dpl_pVMLICurr,ebx       ; init dpl_pVMLICurr
        jmp     dpl100

dpl10:  push    ds                      ; save ds
        FlatContext <ds>,ax             ; DS = Flat

        cmp     dpl_target_hob,0
        jz      dpl15

        mov     ax,[ebx].vmli_lh_hob
        cmp     ax,dpl_target_hob
        jz      dpl15
        pop     ds                      ; restore ds
        jmp     dpl80

dpl15:  mov     ax,word ptr [ebx].vmli_cs
        mov     dpl_li_cs,ax
        mov     eax,[ebx].vmli_eip
        mov     dpl_li_eip,eax
        mov     eax,[ebx].vmli_phlock
        mov     dpl_li_phlock,eax
        mov     eax,[ebx].vmli_lh_page
        and     eax,000fffffh
        shl     eax,12
        mov     dpl_li_address,eax
        mov     ax,word ptr [ebx].vmli_lh_page+2
        shr     ax,4
        mov     dpl_li_flg,ax
        mov     ax,[ebx].vmli_lh_hptda
        mov     dpl_li_hptda,ax
        mov     ax,[ebx].vmli_lh_npages
        mov     dpl_li_npages,ax
        mov     ax,[ebx].vmli_lh_hob
        mov     dpl_li_hob,ax
        mov     ax,[ebx].vmli_lh_sig
        mov     dpl_li_sig,ax

        mov     eax,[ebx].vmli_lh_page
        mov     ecx,eax
        shr     eax,16
        and     ax,000fh
        mov     edx,eax
        mov     eax,ecx
        shr     eax,20
        and     ah,0fh
        add     ax,dx
        add     ax,[ebx].vmli_lh_hptda
        add     ax,[ebx].vmli_lh_npages
        add     ax,[ebx].vmli_lh_hob
        add     ax,cx
        mov     dpl_li_csig,ax

        mov     esi,[ebx].vmli_phlock
        mov     eax,[esi].vmlh_s_fs
        and     eax,000fffffh
        shl     eax,12
        mov     dpl_li_address1,eax
        mov     ax,word ptr [esi].vmlh_s_fs+2
        shr     ax,4
        mov     dpl_li_flg1,ax
        mov     ax,[esi].lh_hptda
        mov     dpl_li_hptda1,ax
        mov     ax,[esi].lh_npages
        mov     dpl_li_npages1,ax
        mov     ax,[esi].lh_hob
        mov     dpl_li_hob1,ax
        mov     ax,[esi].lh_sig
        mov     dpl_li_sig1,ax

        mov     eax,[esi].vmlh_s_fs
        mov     ecx,eax
        shr     eax,16
        and     ax,000fh
        mov     edx,eax
        mov     eax,ecx
        shr     eax,20
        and     ah,0fh
        add     ax,dx
        add     ax,[esi].lh_hptda
        add     ax,[esi].lh_npages
        add     ax,[esi].lh_hob
        add     ax,cx
        mov     dpl_li_csig1,ax

        pop     ds                      ; restore ds
     assumeDATA ds                      ;

        mov     li_pvmli,ebx
        mov     ax,dpl_li_cs
        mov     li_cs,ax
        mov     eax,dpl_li_eip
        mov     li_eip,eax
        mov     eax,dpl_li_phlock
        mov     li_phlock,eax
        mov     eax,dpl_li_address
        mov     li_address,eax
        mov     ax,dpl_li_flg
        mov     li_flg,ax
        mov     ax,dpl_li_hptda
        mov     li_hptda,ax
        mov     ax,dpl_li_npages
        mov     li_npages,ax
        mov     ax,dpl_li_sig
        mov     li_sig,ax
        mov     ax,dpl_li_csig
        mov     li_csig,ax
        mov     ax,dpl_li_hob
        mov     li_hob,ax

        cmp     [dpl_curr_hob],0
        jz      short dpl50
        cmp     [dpl_curr_hob],ax
        jz      short dpl55
        jmp     dpl80
dpl50:  mov     [dpl_curr_hob],ax

dpl55:  push    ds                      ; save ds
        FlatContext <ds>,ax             ; DS = Flat
        inc     [ebx].vmli_flags
        pop     ds                      ; restore ds
     assumeDATA ds                      ;

        push    ebx

        call    dpl200
        mov     si,dataOFFSET PrintLock ; si = PrintLock opcode list
        Pcall   OpInterpret             ; interpret

        mov     eax,dpl_li_address1
        mov     li_address,eax
        mov     ax,dpl_li_flg1
        mov     li_flg,ax
        mov     ax,dpl_li_hptda1
        mov     li_hptda,ax
        mov     ax,dpl_li_npages1
        mov     li_npages,ax
        mov     ax,dpl_li_hob1
        mov     li_hob,ax
        mov     ax,dpl_li_sig1
        mov     li_sig,ax
        mov     ax,dpl_li_csig1
        mov     li_csig,ax

        mov     eax,dpl_li_address
        cmp     eax,dpl_li_address1
        jnz     short dpl66
        mov     ax,dpl_li_flg
        cmp     ax,dpl_li_flg1
        jnz     short dpl66
        mov     ax,dpl_li_hptda
        cmp     ax,dpl_li_hptda1
        jnz     short dpl66
        mov     ax,dpl_li_npages
        cmp     ax,dpl_li_npages1
        jnz     short dpl66
        mov     ax,dpl_li_hob
        cmp     ax,dpl_li_hob1
        jnz     short dpl66
        mov     ax,dpl_li_sig
        cmp     ax,dpl_li_sig1
        jnz     short dpl66
        mov     ax,dpl_li_csig
        cmp     ax,dpl_li_csig1
        jz      short dpl70

dpl66:  mov     cx,34
        Pcall   tab
        call    dpl200
        mov     si,dataOFFSET PrintLock1; si = PrintLock1 opcode list
        Pcall   OpInterpret             ; interpret

dpl70:  pop     ebx

dpl80:  test    [dpl_flags],DOA_FLINK
        jnz     short dpl100

dpl90:  push    ds                      ; save ds
        FlatContext <ds>,ax             ;
dpl91:  mov     ebx,[ebx].vmli_next     ; ebx = ebx->next
        or      ebx,ebx
        jz      short dpl93
dpl92:  cmp     [ebx].vmli_flags,0
        jnz     short dpl91
dpl93:  pop     ds                      ; restore ds
     assumeDATA ds                      ;
        cmp     [dpl_curr_hob],0
        jnz     short dpl95
        mov     dpl_pVMLICurr,ebx       ; update dpl_pVMLICurr
dpl95:  or      ebx,ebx                 ; next = null ?
        jnz     dpl10                   ;  jmp if no
        cmp     [dpl_curr_hob],0        ; curr_hob = 0 ?
        jz      dplx                    ;  jmp if yes

dpl100: mov     [dpl_curr_hob],0        ; curr_hob = 0
        mov     ebx,dpl_pVMLICurr       ;
        jmp     short dpl90

dpl200:
        cmp     [dpl_cline],0
        jnz     short dpl201
        putstr  <"   pvmli    cs    eip     phlock   cpg      va    flg  hptda hob sig  csig">
        Pcall   crlf
        mov     [dpl_cline],LINES_PER_PAGE ; number lines per page
dpl201: dec     [dpl_cline]             ; one more line printed
        ret

dplx:
EndProc
;*** End 82818  *************************************************


;***    PrintOwner
;
;       Prints the owner of the physical memory.
;
;       Pcall   PrintOwner
;
;       ENTRY   (EDX) = handle
;               (DI)  = cached object record
;       EXIT    NONE
;       USES    EAX, EBX, ECX, EDX, ESI, EDI, Flags

DefProc PrintOwner, NEAR, LOCAL
    assumeDATA <ds, es, ss>
    LocVar TmpAddr, <size AddrS>
BeginProc
        mov     bx,dx                   ; (BX) = handle
        mov     cx,[di-obu0].ob_fs      ; (CX) = flags
        mov     si,[di-obu0].ob_hobowner; (SI) = owner

        mov     dx,dataOFFSET freemsg
        or      si,si                   ; is the handle free?
        jz      pto90                   ; jmp if free

        cmp     si,LDRMTEOWNER
        jnz     short pto30
        mov     dx,dataOFFSET mtemsg
        Pcall   rprbuf
        mov     dx,bx                   ; (DX) = handle
        Pcall   PrintMTE
        jmp     ptox

pto30:  cmp     si,TKPTDAOWNER
        jnz     short pto40
        mov     dx,dataOFFSET ptdamsg
        Pcall   rprbuf
        mov     dx,bx                   ; (DX) = handle
        Pcall   PrintPTDA
        jmp     ptox

pto40:  cmp     si,SELLDTOWNER
        jnz     short pto50
        mov     dx,dataOFFSET ldtmsg
        Pcall   rprbuf
        mov     dx,bx                   ; (DX) = handle
        Pcall   PrintLDT
        jmp     ptox

pto50:  cmp     si,VMMAXOWNER           ; highest simple owner equate
        ja      pto80
        cmp     si,VMMINOWNER           ; lowest simple owner equate
        jb      short pto60

        sub     si,VMMINOWNER
        shl     si,1
        mov     dx,[OwnerMsgs+si]
        Pcall   rprbuf

        Pcall   blank
        mov     si,[di-obu0].ob_hobmte  ; (SI) = allocator
        cmp     si,VMMAXOWNER           ; highest simple owner equate
        ja      short ptox
        cmp     si,VMMINOWNER           ; lowest simple owner equate
;155531   jb      short ptox
;155531 also format the hobmte with system owners - need this now FSDs and DDs use HMTE
        jae     short pto55             ;155531
        cmp     si,0                    ;155531
        jz      ptox                    ;155531
        mov     dx,si                   ;155531 (DX) = owner handle
        Pcall   PrintMTE                ;155531
        jmp     short ptox              ;155531
pto55:                                  ;155531

        sub     si,VMMINOWNER
        shl     si,1
        mov     dx,[OwnerMsgs+si]
        jmp     pto90

pto60:  mov     dx,si                   ; (DX) = owner handle
        lea     bx,TmpAddr

        Pcall   GetObjectAddr           ; validate MTE handle
        jnc     short pto65             ; jump if handle ok
        Pcall   GetPseudoObjectAddr     ; validate PTDA handle
        jc      short pto80             ; jump if bad handle

pto65:  Pcall   GetWord                 ; fetch MTE signature at offset 0
                                        ; BUGBUG assumes mte layout - should
                                        ;        use struct definition
        jc      short pto80
        and     dx,MTEFORMATMASK
        cmp     dx,MTEFORMATLX
        jz      short pto70
        cmp     dx,MTEFORMATNE
        jz      short pto70
        Pcall   GetWordOff, <word ptr ptda_signature, 0>
        jc      short pto80
        cmp     dx,"DT"
        jnz     short pto80
        mov     dx,dataOFFSET privmsg
        Pcall   rprbuf
        mov     dx,si                   ; (DX) = owner handle
        Pcall   PrintPTDA
        jmp     short ptox

pto70:  mov     dx,dataOFFSET sharemsg
        Pcall   rprbuf
        mov     dx,si                   ; (DX) = owner handle
        Pcall   PrintMTE
        jmp     short ptox

pto80:  mov     dx,dataOFFSET UNKNOWNmsg
pto90:  Pcall   rprbuf
ptox:
EndProc


;***    PrintLDT
;
;       Prints the name of owner of the LDT
;
;       Pcall   PrintLDT
;
;       ENTRY   (DX) = LDT handle
;       EXIT    NONE
;       USES    AX, BX, CX, DX, SI, DI, Flags

DefProc PrintLDT, NEAR, LOCAL
    assumeDATA <ds, es, ss>
    LocVar TmpAddr, <size AddrS>
BeginProc
        mov     si,dx                   ; (SI) = handle to match
        DosContext ds                   ; (DS) = DosGroup
        mov     cx,[MaxThreads]         ; (CX) = number of process slots
        DataContext ds

pld1:   mov     ax,cx                   ; (AX) = slot number
        lea     bx,TmpAddr
        Pcall   GetPTDAaddr             ; [TmpAddr] filled in
        jc      short pld2

        Pcall   GetWordOff, <word ptr ptda_ldthandle, 0>
        jc      short pld2

        cmp     dx,si                   ; do the handles match?
        jnz     short pld2

        Pcall   GetWordOff, <word ptr ptda_handle, 0>
        jc      short pld2

        push    si
        Pcall   PrintPTDA               ; print owner
        pop     si
        jmp     short pld3

pld2:   loop    pld1
pld3:
EndProc


;***    PrintPTDA
;
;       Prints the pid of the process for the PTDA
;
;       Pcall   PrintPTDA
;
;       ENTRY   (DX) = PTDA handle
;       EXIT    NONE
;       USES    AX, BX, CX, DX, SI, DI, Flags

DefProc PrintPTDA, NEAR, LOCAL
    assumeDATA <ds, es, ss>
    LocVar TmpAddr, <size AddrS>
BeginProc
        lea     bx,TmpAddr
        Pcall   GetPseudoObjectAddr
        jc      short pptx
        Pcall   GetWordOff, <word ptr ptda_signature, 0>
        jc      short pptx
        cmp     dx,"DT"
        jnz     short pptx
        Pcall   GetWordOff, <word ptr ptda_Pid, 0>
        jc      short pptx
        Pcall   out16                   ; print Pid
        push    dx                      ; save pid
        Pcall   GetWordOff, <word ptr ptda_module, 0>
        pop     si                      ; restore pid
        jc      short pptx

        or      dx,dx                   ; valid mte handle?
        jnz     short ppt20             ; jmp if so

        mov     dx,dataOFFSET SYIthreadmsg
        cmp     si,1                    ; else pid 1 is the ager
        jz      short ppt10

        Pcall   GetWordOff, <word ptr ptda_ProcType, 0>
        jc      short pptx
        cmp     dx,PT_REALMODE
        jnz     short pptx

        mov     dx,dataOFFSET VDMmsg    ; is a vdm
ppt10:  Pcall   blank
        Pcall   rprbuf                  ; print pseudo name
        jmp     short pptx

ppt20:  Pcall   blank
        Pcall   PrintMTE
pptx:
EndProc


;***    PrintMTE
;
;       Prints the name in the MTE for owner
;
;       Pcall   PrintMTE
;
;       ENTRY   (DX) = MTE handle
;       EXIT    NONE
;       USES    AX, BX, CX, DX, SI, DI, Flags

DefProc PrintMTE, NEAR, LOCAL
    assumeDATA <ds, es, ss>
        cmp     dx,VMMAXOWNER           ; highest simple owner equate
        ja      pmtx
        cmp     dx,VMMINOWNER           ; lowest simple owner equate
        jb      short pmt60

        mov     si,dx
        sub     si,VMMINOWNER
        shl     si,1
        mov     dx,[OwnerMsgs+si]
        jmp     short pmt90

pmt60:  mov     bx,2                    ; (BX) = flag: drive & last component
        xor     di,di                   ; (DI) = name buffer, 0 for cache
        Pcall   GetMTEName              ; (DI) = cached asciiz name
        jc      pmtx

        mov     dx,di
        mov     dx,di
pmt90:  Pcall   rprbuf                  ; print mte path
pmtx:
EndProc


;***    DOAPrintContext
;
;       The routine dumps context record(s) in the specified range
;
;       ENTRY   (EAX) = match address if DOA_MATCH set in (EBX)
;               (EBX)  = display flags
;               (ECX) = number of context records to display
;               (EDX) = start handle
;               (SI)  = number of lines printed
;       EXIT    (EDX) = next handle
;               (SI)  = number of lines printed
;       USES    ALL

DefProc DOAPrintContext,NEAR,LOCAL
    assumeDATA <ds, es, ss>
    LocVar dco_flags, DWORD
    LocVar dco_count, DWORD
    LocVar dco_hco, DWORD
    LocVar dco_hconext, DWORD
    LocVar dco_addr, <size AddrS>
    LocVar dco_addrbase, <size AddrS>
BeginProc
        DOAENTRY <"context">
        mov     [dco_flags],ebx
        mov     [dco_count],ecx
        mov     [dco_hco],edx
        mov     [dco_hconext],0

        lea     bx,[dco_addrbase]
        xor     cx,cx
        mov     edx,1
        Pcall   GetContextTable
        jc      short dco20

dco00:  lea     bx,[dco_addr]
        mov     ecx,[dco_flags]
        and     cx,DOA_LIN
        .errnz  (DOA_LIN and 0ffff0000h)
        mov     edx,[dco_hco]
        Pcall   GetContextTable
        jc      short dco20

        mov     [dco_hco],edx
        mov     dx,size vmco_s
        Pcall   GetCache                ; (DI) = cache buffer

;       We get here with carry set when the context data is past the end
;       of the context record array or when a page fault is encountered.
;       This means we've finished dumping contexts - So clean up and exit.

dco20:  cmc
        jnc     dcox                    ; finished - (end of table reached)

;       Since a context record is 4 bytes long, there's no proper way to
;       tell if the record is free by examining the structure.  We cheat
;       here by depending on the fact that valid co_hobptda fields are
;       always smaller than the high word of a BMP link.  If the BMP link
;       looks valid (is a pointer into the BMP object or is NULL), then
;       we assume the record is free.

        mov     eax,[di]
        cmp     [dco_addrbase].AddrOff,eax
        jbe     short dco30             ; jmp if entry is free
        or      eax,eax
        jz      short dco30             ; jmp if entry is free

        mov     si,dataOFFSET PrintContext
        test    [dco_flags],DOA_INUSE
        jnz     short dco40             ; jmp if should dump busy records
        jmp     dco80

dco30:  test    [dco_flags],DOA_FREE
        jz      dco80                   ; jmp if should not dump free records
        mov     si,dataOFFSET PrintContextFree

dco40:
;;;;;;; movzx   eax,[di].co_hconext
        movzx   eax,[di].co_fb
        and     al,CO_HCOH
        shl     eax,11
        mov     ax,[di].co_hconext
        mov     [dco_hconext],eax
        test    [dco_flags],DOA_FINDROOT
        jz      short dco50
        putstr  <"*hco=">
        jmp     short dco55

dco50:  putstr  <" hco=">
dco55:
        mov     dx,[dco_hco].LowWord
        mov     ax,[dco_hco].HighWord
;;;;;;; Pcall   out16                   ; print handle number
        Pcall   Out20
        putstr  <" pco=">
        mov     dx,[dco_addr].AddrOff.HighWord
        Pcall   out16                   ; print high address
        mov     dx,[dco_addr].AddrOff.LowWord
        Pcall   out16                   ; print low address
        Pcall   OpInterpret
        mov     eax,[di]
        cmp     [dco_addrbase].AddrOff,eax
        jbe     short dco70             ; jmp if entry is free
        movzx   edx,[di].co_hobptda
        Pcall   PrintPTDA               ; print owner
dco70:  Pcall   crlf

        test    [dco_flags],DOA_FINDROOT
        jz      short dco80             ; jmp if should not follow chain
        mov     edx,[dco_hconext]
dc075:  or      edx,edx
        jz      short dco80
        mov     ebx,DOA_INUSE+DOA_DATA
        mov     ecx,1
        Pcall   DOAPrintContext         ; recurse to print one context record
        jnc     short dc075

dco80:  and     [dco_flags],not DOA_LIN
        inc     [dco_hco]               ; skip to next handle
        dec     [dco_count]
        jnz     dco00                   ; loop
dcox:   mov     edx,[dco_hconext]
EndProc


;***    DOAPrintPF
;
;       The routine dumps the page frame(s) in the specified range
;
;       ENTRY   (EAX) = match address if DOA_MATCH set in (EBX)
;               (BX)  = display flags
;               (ECX) = number of object records to display
;               (EDX) = start frame/laddr
;               (SI)  = number of lines printed
;       EXIT    (SI)  = number of lines printed
;       USES    ALL

DefProc DOAPrintPF,NEAR,LOCAL
    assumeDATA <ds, es, ss>
    LocVar dpf_flags, DWORD
    LocVar dpf_count, DWORD
    LocVar dpf_pf, DWORD
    LocVar dpf_pfnext, DWORD
    LocVar dpf_addr, <size AddrS>
BeginProc
        DOAENTRY <"pf">
        mov     [dpf_flags],ebx
        mov     [dpf_count],ecx
        mov     [dpf_pf],edx
        mov     [dpf_pfnext],0

dpf00:  lea     bx,[dpf_addr]
        mov     ecx,[dpf_flags]
        and     ecx,DOA_LIN
        xor     [dpf_flags],ecx         ; clear DOA_LIN bit
        mov     edx,[dpf_pf]
        push    edx
        inc     edx
        test    [dpf_flags],DOA_FLINK or DOA_BLINK
        jz      short dpf10
        mov     edx,-1                  ; set an invalid link
dpf10:  mov     [dpf_pfnext],edx
        pop     edx
        Pcall   GetPFTable
        jc      short dpf20

        mov     [dpf_pf],edx
        mov     dx,PFSIZE
        Pcall   GetCache                ; (DI) = cache buffer
        jnc     short dpf20
        mov     edx,-1

;       We get here with carry set when the frame is past the end
;       of the pf array OR when the frame is an invalid frame between
;       two valid ranges.  The former means we've finished dumping the
;       array (edx is -1) - So clean up and exit.  The latter means we
;       should just skip to the next frame.

dpf20:  jnc     short dpf25
        cmp     edx,-1                  ; are there any more?
        jz      dpfx                    ; jmp if finished - (at end of table)
        test    [dpf_flags],DOA_FLINK or DOA_BLINK
        jz      dpf22
        jmp     dpfx
dpf22:  mov     [dpf_pf],edx
        jmp     short dpf00             ; else bad frame (dump next good frame)

dpf25:  test    dword ptr [di].xpf_flags,XPF_FREE
        jnz     short dpf30             ; jmp if entry is free

;;;rjm 153574
        test    [dpf_flags],DOA_IDLE
        jz      dpf28                   ; jmp if should not be idle
        mov     eax,[di]                ; flat:(eax) = pvp
        push    ds
        FlatContext     ds
        test    [eax].xvp_flags,VP_PFIDLE ; idle?
        pop     ds
        jnz     dpf60

dpf28:  test    [dpf_flags],DOA_INUSE
;;;RJM 153574
        jnz     short dpf60             ; jmp if should dump busy records
        jmp     short dpf80

dpf30:  test    [dpf_flags],DOA_FREE
        jz      short dpf80             ; jmp if should not dump free records

dpf60:  test    [dpf_flags],DOA_FLINK or DOA_BLINK
        jz      short dpf62

        lea     bx,[dpf_addr]           ; setup for GetPFTable call
        xor     cx,cx

        mov     edx,[di].xpf_flink      ; (EDX) = flink frame + trash
        test    [dpf_flags],DOA_FLINK
        jnz     short dpf61

        mov     edx,[di].xpf_blink      ; (EDX) = blink frame + trash

;;;rjm dpf61:  and     edx,PAGEMASK            ; (EDX) = link (frame)
dpf61:  and     edx,0fffffh             ; (EDX) = link (frame) 153574
        mov     [dpf_pfnext],edx

dpf62:  mov     dx,[dpf_addr].AddrOff.HighWord
        Pcall   out16                   ; print high address
        mov     dx,[dpf_addr].AddrOff.LowWord
        Pcall   out16                   ; print low address

        mov     si,dataOFFSET PrintFreePF
        test    dword ptr [di].xpf_flags, XPF_FREE ;free pf?
        jnz     dpf70                   ; if free, jmp to print it

        mov     si,dataOFFSET PrintIdlePF
        mov     eax,[di]                ; flat:(eax) = pvp
        push    ds
        FlatContext     ds
        test    [eax].xvp_flags,VP_PFIDLE ; idle?
        pop     ds
        jnz     dpf70                   ; if idle, jmp to print it

        mov     si,dataOFFSET PrintBusyPF ; must be busy

dpf70:  Pcall   OpInterpret
        mov     ax,[dpf_pf].HighWord
        mov     dx,[dpf_pf].LowWord
        Pcall   Out20                   ; print frame number
        Pcall   crlf
dpf80:  mov     edx,[dpf_pfnext]
        mov     [dpf_pf],edx            ; set next handle
        dec     [dpf_count]
        jnz     dpf00                   ; loop
dpfx:
EndProc


;***    DOAPrintVP
;
;       The routine dumps the virtual frame(s) in the specified range
;
;       ENTRY   (EAX) = match address if DOA_MATCH set in (EBX)
;               (BX)  = display flags
;               (ECX) = number of object records to display
;               (EDX) = start vp indexladdr
;               (SI)  = number of lines printed
;       EXIT    (SI)  = number of lines printed
;       USES    ALL

DefProc DOAPrintVP,NEAR,LOCAL
    assumeDATA <ds, es, ss>
    LocVar dvp_flags, DWORD
    LocVar dvp_count, DWORD
    LocVar dvp_vp, DWORD
    LocVar dvp_cline, WORD
    LocVar dvp_vpnext, DWORD
    LocVar dvp_addr, <size AddrS>
BeginProc
        DOAENTRY <"vp">
        mov     [dvp_flags],ebx
        mov     [dvp_count],ecx
        mov     [dvp_vp],edx
        mov     [dvp_cline],si
        mov     [dvp_vpnext],0

dvp00:  lea     bx,[dvp_addr]
        mov     ecx,[dvp_flags]
        and     ecx,DOA_LIN
        xor     [dvp_flags],ecx         ; clear DOA_LIN bit
        mov     edx,[dvp_vp]
        push    edx
        inc     edx
        test    [dvp_flags],DOA_FLINK or DOA_BLINK
        jz      short dvp10
        xor     edx,edx                 ; set an invalid link
dvp10:  mov     [dvp_vpnext],edx
        pop     edx
        Pcall   GetVPTable
        jc      short dvp20

        mov     [dvp_vp],edx
        mov     dx,VPSIZE
        Pcall   GetCache                ; (DI) = cache buffer

;       We get here with carry set when the frame is past the end
;       of the vp array.  This means we've finished dumping the
;       array - So clean up and exit.

dvp20:  cmc
        jnc     dvpx                    ; finished - (end of table reached)

        cmp     [di].avp_refcount,0     ; is it free?
        jz      short dvp35             ; jmp if entry is free

        test    [dvp_flags],DOA_INUSE

;RJM 154741
;rjm    jnz     short dvp60             ; jmp if should dump busy records
        jnz     short dvp62             ; rjm jmp if should dump busy records
; if we hit a non-free vp and we are asking to run the link
; then exit, since we loop if we don't because free vps are not chained on
; a simple linked list - we can hit a non-free vp at the end of a chain.
; BUGBUG we don't skip to he next bundle of free vps, just chain the current
; vp.
; If we are just looking for free records then loop round.
        test    [dvp_flags],DOA_FLINK or DOA_BLINK ;rjm
        jz      dvp80                   ; rjm
        jmp     dvpx                    ; rjm
;rjm    jmp     dvp80
;RJM 154741


dvp35:  test    [dvp_flags],DOA_FREE
        jz      dvp80                   ; jmp if should not dump free records

dvp60:  test    [dvp_flags],DOA_FLINK or DOA_BLINK
        jz      short dvp62
        mov     edx,[di].fvp_flink      ; (EDX) = vp_flink
        test    [dvp_flags],DOA_FLINK
        jnz     short dvp61
        mov     edx,[di].fvp_blink      ; (EDX) = vp_blink
dvp61:  mov     [dvp_vpnext],edx
        or      [dvp_flags],DOA_LIN     ; set DOA_LIN bit

dvp62:  putstr  <"VPI="
        mov     dx,[dvp_vp].LowWord
        Pcall   out16                   ; print vp index
        putstr  <" pVP=">
        mov     dx,[dvp_addr].AddrOff.HighWord
        Pcall   out16                   ; print high address
        mov     dx,[dvp_addr].AddrOff.LowWord
        Pcall   out16                   ; print low address

        mov     si,dataOFFSET PrintFreeVP
        cmp     [di].avp_refcount,0     ; free?
        jz      short dvp75             ; if free, jmp to print it

        mov     si,dataOFFSET PrintBusyVP
        test    [di].xvp_flags,VP_SOW
        jz      short dvp65              ; jmp if not Swap On Write
        putstr  <" SOW">
        jmp     short dvp71

dvp65:  test    [di].xvp_flags,VP_RESIDENT
        jz      short dvp67                      ; jmp if not resident
        putstr  <" Res">
        jmp     short dvp71

dvp67:  test    [di].xvp_flags,VP_DISCARDABLE
        jz      short dvp69                      ; jmp if not discardable
        putstr  <" Dsc">
        jmp     short dvp71

dvp69:  putstr  <" Swp">

dvp71:  test    [di].xvp_flags,VP_PF    ; is a pf attached?
        jnz     short dvp73                   ; jmp if pf attached
        putstr  <" Block=">
        jmp     short dvp75                   ; print frame

dvp73:  putstr  <" Frame=">

dvp75:  Pcall   OpInterpret
        Pcall   crlf
dvp80:  mov     edx,[dvp_vpnext]
        mov     [dvp_vp],edx            ; set next handle
        dec     [dvp_count]
        jnz     dvp00                   ; loop
dvpx:
EndProc


;***    GetObjectAddr
;
;       Pcall   GetObjectAddr
;
;       ENTRY   (BX) = AddrS struc to put address
;               (DX) = memory manager handle
;       EXIT    If carry clear,
;                       no error
;               If carry set, invalid handle
;                       (AX) = error code
;       USES    EAX, Flags

DefProc GetObjectAddr,NEAR,PUBLIC
    assumeDATA <ds, es, ss>
        SaveReg <cx, edx, si>
        push    bx
        xor     cx,cx
        movzx   edx,dx
        Pcall   GetObjectTable
        jc      short goa20

        mov     dx,size vmob_s - obu0
        Pcall   GetCache                ; (DI) = cache buffer
goa20:  pop     bx
        jc      short goax

        mov     ax,DEBERR_INVALID_ADDR_TYPE
        test    [di-obu0].ob_fs,OB_PSEUDO
        stc
        jnz     short goax

        push    bx
        xor     cx,cx
        movzx   edx,word ptr [di].ob_har ; (EDX) = arena record handle
        Pcall   GetArenaTable
        jc      short goa40

        mov     dx,size vmar_s - aru4
        Pcall   GetCache                ; (DI) = cache buffer
goa40:  pop     bx
        jc      short goax

        mov     dx,[di].ar_union0.LowWord ; (DX) = ar_f + ar_ipg.low4bits
        mov     ax,DEBERR_INVALID_ADDR_TYPE
        test    dx,AR_INUSE             ; ar_f
        stc
        jz      short goax              ; jmp if arena record is free
        mov     ax,[di].ar_union0.HighWord ; (AX:DX) = ar_ipg << PAGESHIFT
        and     dx,not (PAGESIZE - 1)
        Pcall   FillLinAddr, <bx, dx, ax>
        clc
goax:   RestReg <si, edx, cx>
EndProc


;***    GetPseudoObjectAddr
;
;       Pcall   GetPseudoObjectAddr
;
;       ENTRY   (BX) = AddrS struc to put address
;               (DX) = memory manager handle
;       EXIT    If carry clear,
;                       no error
;               If carry set, invalid handle
;                       (AX) = error code
;       USES    EAX, Flags

DefProc GetPseudoObjectAddr,NEAR,PUBLIC
    assumeDATA <ds, es, ss>
        SaveReg <cx, edx, si>
        push    bx
        xor     cx,cx
        movzx   edx,dx
        Pcall   GetObjectTable
        jc      short gpo20

        mov     dx,size vmob_s - obu0
        Pcall   GetCache                ; (DI) = cache buffer
gpo20:  pop     bx
        jc      short gpox

        mov     ax,DEBERR_INVALID_ADDR_TYPE
        test    [di-obu0].ob_fs,OB_PSEUDO
        stc
        jz      short gpox

        mov     ax,[di-obu0].ob_va.HighWord
        mov     dx,[di-obu0].ob_va.LowWord
        Pcall   FillLinAddr, <bx, dx, ax>
        clc
gpox:   RestReg <si, edx, cx>
EndProc


;***    GetObjectTable
;
;       Pcall   GetObjectTable
;
;       ENTRY   (BX)  = pointer to AddrS
;               (CX)  = laddr flag: 0 implies handle
;               (EDX) = handle/laddr
;       EXIT    If carry clear, no errors
;                       (EDX) = handle
;               If carry set,
;                       (AX) = error code
;       USES    EAX, EDX, Flags

DefProc GetObjectTable,NEAR,LOCAL
    assumeDATA <ds, es, ss>
        push    ds
        FlatContext ds
        mov     eax,[_pobvmOne]
        pop     ds
    assumeDATA <ds>
        jcxz    short got00             ; jmp if handle given

        sub     edx,eax                 ; else convert laddr to handle
        jc      short got80
        push    eax
        push    ebx
        mov     eax,edx
        xor     edx,edx
        mov     ebx,size vmob_s - obu0  ; (ebx) = size
        idiv    ebx                     ; (eax) = (edx:eax)/size
        mov     edx,eax                 ; (edx) = handle
        pop     ebx
        pop     eax
        inc     edx

got00:  or      edx,edx
        .errnz  HOBNULL
        jz      short got80
        dec     edx                     ; (edx) = handle - 1
;       add     eax,edx                 ; (eax) += handle-1 * size vmob_s
        lea     eax,[eax+edx*8]
        lea     eax,[eax+edx*8]
        .errnz (size vmob_s - obu0 - (1 + 8 + 7))
        inc     edx                     ; restore edx
        Pcall   FillLinAddr, <bx, eax>
        clc
        jmp     short gotx

got80:  mov     ax,DEBERR_OFFSET_PAST_LIMIT
        stc
gotx:
EndProc


;***    GetArenaTable
;
;       Pcall   GetArenaTable
;
;       ENTRY   (BX)  = pointer to AddrS
;               (CX)  = laddr flag: 0 implies handle
;               (EDX) = handle/laddr
;       EXIT    If carry clear, no errors
;                       (EDX) = handle
;               If carry set,
;                       (AX) = error code
;       USES    EAX, EDX, Flags

DefProc GetArenaTable,NEAR,LOCAL
    assumeDATA <ds, es, ss>
        push    ds
        FlatContext ds
        mov     eax,[_parvmOne]
        pop     ds
    assumeDATA <ds>
        jcxz    short gat00             ; jmp if handle given

        sub     edx,eax                 ; else convert laddr to handle
        jc      short gat80
        push    eax
        push    ebx
        mov     eax,edx
        xor     edx,edx
        mov     ebx,size vmar_s - aru4  ; (ebx) = size
        idiv    ebx                     ; (eax) = (edx:eax)/size
        mov     edx,eax                 ; (edx) = handle
        pop     ebx
        pop     eax
        inc     edx

gat00:  or      edx,edx
        .errnz  HARNULL
        jz      short gat80
        push    edx
        push    ecx
        dec     edx                     ; (edx) = handle - 1= index
        lea     ecx, [edx*2]            ; (ecx) = index*2
        lea     edx,[edx+edx*4]         ; (edx) = index*5
        lea     edx,[ecx+edx*4]         ; (edx) = index * (size vmar_s)
        .errnz  (size vmar_s - aru4 -(4 * (1+4)) - 2)
        lea     eax,[eax+edx]           ; (eax) = laddr of arena record
        pop     ecx
        pop     edx                     ; restore edx
        Pcall   FillLinAddr, <bx, eax>
        clc
        jmp     short gatx

gat80:  mov     ax,DEBERR_OFFSET_PAST_LIMIT
        stc
gatx:
EndProc


;***    GetContextTable
;
;       Pcall   GetContextTable
;
;       ENTRY   (BX)  = pointer to AddrS
;               (CX)  = laddr flag: 0 implies handle
;               (EDX) = handle/laddr
;       EXIT    If carry clear, no errors
;                       (EDX) = handle
;               If carry set,
;                       (AX) = error code
;       USES    EAX, EDX, Flags

DefProc GetContextTable,NEAR,LOCAL
    assumeDATA <ds, es, ss>
        push    ds
        FlatContext ds
        mov     eax,[_pcovmOne]
        pop     ds
    assumeDATA <ds>
        jcxz    short gct00             ; jmp if handle given

        sub     edx,eax                 ; else convert laddr to handle
        jc      short gct80

        push    eax
        push    ecx
        mov     eax, edx
        xor     edx, edx
        mov     ecx, size vmco_s
        div     ecx
        mov     edx, eax
        inc     edx
        pop     ecx
        pop     eax
;;;;;;; push    ax
;;;;;;; push    cx
;;;;;;; mov     ax, dx
;;;;;;; shr     edx, WORDSHIFT
;;;;;;; mov     cx,size vmco_s
;;;;;;; div     cx                      ; (dx:ax)/size
;;;;;;; mov     dx,ax                   ; (edx) = (edx)/size
;;;;;;; inc     edx
;;;;;;; pop     cx
;;;;;;; pop     ax

gct00:  or      edx,edx
        .errnz  HCONULL
        jz      short gct80
        dec     edx                     ; (edx) = handle - 1
        push    ecx
        mov     ecx, edx
        shl     ecx, 2                  ; multiply by 4
        add     ecx, edx                ; (ecx) = edx*5
        .errnz (size vmco_s - 5)
        lea     eax,[eax+ecx]           ; (eax) = laddr of context record
        pop     ecx
        inc     edx                     ; restore edx
        Pcall   FillLinAddr, <bx, eax>
        clc
        jmp     short gctx

gct80:  mov     ax,DEBERR_OFFSET_PAST_LIMIT
        stc
gctx:
EndProc


;***    GetAliasTable
;
;       Pcall   GetAliasTable
;
;       ENTRY   (BX)  = pointer to AddrS
;               (CX)  = laddr flag: 0 implies handle
;               (EDX) = handle/laddr
;       EXIT    If carry clear, no errors
;                       (EDX) = handle
;               If carry set,
;                       (AX) = error code
;       USES    EAX, EDX, Flags

DefProc GetAliasTable,NEAR,LOCAL
    assumeDATA <ds, es, ss>
        push    ds
        FlatContext ds
        mov     eax,[_palVMAliases]
        pop     ds
    assumeDATA <ds>
        jcxz    short glt00             ; jmp if handle given

        sub     edx,eax                 ; else convert laddr to handle
        jc      short glt80
        push    ax
        push    cx
        mov     ax,dx
        shr     edx,WORDSHIFT
        mov     cx,size vmsal_s
        div     cx                      ; (dx:ax)/size
        mov     dx,ax                   ; (edx) = (edx)/size
        inc     edx
        pop     cx
        pop     ax

glt00:  or      edx,edx
        .errnz  HALNULL
        jz      short glt80
        dec     edx                     ; (edx) = handle - 1
        push    ecx
        mov     ecx,edx
        shl     ecx,3                   ; multiply by 8
        .errnz (size vmsal_s - 8)
        lea     eax,[eax+ecx]           ; (eax) = laddr of context record
        pop     ecx
        inc     edx                     ; restore edx
        Pcall   FillLinAddr, <bx,eax>
        clc
        jmp     short gltx

glt80:  mov     ax,DEBERR_OFFSET_PAST_LIMIT
        stc
gltx:
EndProc


;***    GetPFTable
;
;       Pcall   GetPFTable
;
;       ENTRY   (BX)  = pointer to AddrS
;               (CX)  = laddr flag: 0 implies frame no.
;               (EDX) = frame/laddr
;       EXIT    If carry clear, no errors
;                       (EDX) = frame
;               If carry set,
;                       (AX) = error code
;                       (EDX) = next valid frame or -1 if none
;       USES    EAX, EDX, Flags

DefProc GetPFTable,NEAR,LOCAL
    assumeDATA <ds, es, ss>
        push    ds
        FlatContext ds
        mov     eax,[_pft]
        pop     ds
    assumeDATA <ds>
        jcxz    short gpt00             ; jmp if frame given

        sub     edx,eax                 ; else convert laddr to frame
        jc      short gpt80
        push    eax
        push    ecx
        mov     eax,edx
        sub     edx,edx
        mov     ecx,PFSIZE
        div     ecx                     ; (eax) = (edx:eax)/size
        mov     edx,eax
        pop     ecx
        pop     eax

gpt00:  push    edx
        call    ValidateFrame           ; (edx) = ValidateFrame(edx=frame)
        jc      short gpt60
        imul    edx,edx,PFSIZE          ; (edx) = (edx)*size
        add     eax,edx                 ; (eax) = base + (index * size pf_s)
        Pcall   FillLinAddr, <bx, eax>
        clc
gpt60:  pop     edx                     ; restore edx
        jnc     short gptx
        mov     edx,eax
        jmp     short gpt90

gpt80:  mov     edx,-1
gpt90:  mov     ax,DEBERR_OFFSET_PAST_LIMIT
        stc
gptx:
EndProc


;***    ValidateFrame
;
;       Pcall   ValidateFrame
;
;       ENTRY   (EDX) = frame
;       EXIT    If carry clear, no errors
;                       (EAX) = unmodified
;                       (EDX) = index
;               If carry set,
;                       (EAX) = next valid frame or -1 if none
;       USES    EAX, EDX, Flags

DefProc ValidateFrame,NEAR,LOCAL
    assumeDATA <ds, es, ss>
        push    ecx
        push    esi
        push    ds
        FlatContext ds
        mov     ecx,[_pgPageablePAI].pai_nranges
        mov     esi,[_pgPageablePAI].pai_pprt; search for the matching pagerange_s
fti00:  cmp     dword ptr [esi].pr_lastframe,edx
        jae     short fti50             ; jmp if found in range
        add     esi,size pagerange_s
        loop    fti00                   ; jmp if more ranges to check
fti20:  mov     eax,-1                  ; else indicate no more valid frames
ftie:   stc                             ; indicate failure
        jmp     short fti80

fti50:  cmp     dword ptr [esi].pr_firstframe,edx
        jbe     short fti60
        mov     eax,dword ptr [esi].pr_firstframe ; indicate next valid frame
        jmp     short ftie

fti60:  cmp     edx,[_pgPhysMax]        ; make sure it's valid
        ja      short fti20
        clc
fti80:  pop     ds
    assumeDATA <ds>
        pop     esi
        pop     ecx
EndProc


;***    GetVPTable
;
;       Pcall   GetVPTable
;
;       ENTRY   (BX)  = pointer to AddrS
;               (CX)  = laddr flag: 0 implies index
;               (EDX) = vp index/laddr
;       EXIT    If carry clear, no errors
;                       (EDX) = vp index
;               If carry set,
;                       (AX) = error code
;       USES    EAX, EDX, Flags

DefProc GetVPTable,NEAR,LOCAL
    assumeDATA <ds, es, ss>
        push    ds
        FlatContext ds
        mov     eax,[_pgpVPBase]
        pop     ds
    assumeDATA <ds>
        jcxz    short gvt00             ; jmp if index given

        sub     edx,eax                 ; else convert laddr to index
        jc      short gvt80
        push    eax
        push    ebx
        mov     eax,edx
        xor     edx,edx
        mov     ebx,VPSIZE              ; (ebx) = size
        idiv    ebx                     ; (eax) = (edx:eax)/size
        mov     edx,eax                 ; (edx) = index
        pop     ebx
        pop     eax

gvt00:  push    edx
        imul    edx,VPSIZE
        add     eax,edx                 ; (eax) = base + (index * size vp_s)
        push    ds
        FlatContext ds
        mov     edx,[_pgpVPEnd]         ; (edx) = addr of last valid VP
        pop     ds
        assumeDATA <ds>
        cmp     eax,edx
        pop     edx                     ; restore edx
        ja      short gvt80             ; jump if (eax) is past end of table
        Pcall   FillLinAddr, <bx, eax>
        clc
        jmp     short gvtx

gvt80:  mov     ax,DEBERR_OFFSET_PAST_LIMIT
        stc
gvtx:
EndProc


;***    DOAPrintHeap
;
;       ENTRY   (BX)  = pointer to AddrS
;               (CX)  = laddr flag: 0 implies hkrh/hksh
;               (EDX) = hkrh/hksh/laddr
;       EXIT    If carry clear, no errors
;               If carry set,
;                       (AX) = error code
;       USES    EAX, EDX, Flags
;;VMKRHROOWNER
;;VMKRHRWOWNER
;;VMKSHROOWNER
;;VMKSHRWOWNER

DefProc DOAPrintHeap,NEAR,LOCAL
    assumeDATA <ds, es, ss>
        DOAENTRY <"heap">
        putstr  <".mh not yet implemented", CR, LF>
EndProc

CodeSegmentEnd

        end
