        TITLE   SegCheck - internal consistency check
        NAME    SegCheck

;
;       Microsoft Confidential
;       Copyright (C) Microsoft Corporation 1991
;       All Rights Reserved.
;

        .xlist
        include version.inc
        include dosseg.inc
        INCLUDE DOSSYM.INC
        INCLUDE DEVSYM.INC
        include dpb.inc
        include sf.inc
        include int2a.inc
        .list


AsmVars <NET, DEBUG>

DOSCODE SEGMENT
    ASSUME  CS:DOSCODE

if      DEBUG
        allow_getdseg


        BREAK   <SegCheck - validate segments in MSDOS>


zfmt    MACRO   fmts,args
local   a,b
        PUSH    AX
        PUSH    BP
        MOV     BP,SP
If (not sharef) and (not redirector)
DOSDATA  segment
a        db      fmts,0
DOSDATA  ends
        MOV     AX,OFFSET DOSDATA:a
else
        jmp     short b
a       db      fmts,0
if sharef
b:      mov     ax,offset share:a
else
b:      mov     ax,offset netwrk:a
endif
endif
        PUSH    AX
cargs = 2
IRP item,<args>
IFIDN   <AX>,<item>
        MOV     AX,[BP+2]
ELSE
        MOV     AX,item
ENDIF
        PUSH    AX
cargs = cargs + 2
ENDM
        invoke  PFMT
        ADD     SP,Cargs
        POP     BP
        POP     AX
ENDM


;**     SegCheck - assure that segments are correctly set up
;
;       calling sequence:
;               call Segcheck
;               jmp     short l1
;               DB      flags
;               DB      asciz error message string
;          l1:
;
;       flag values:    04 - check ES
;                       02 - check DS
;                       01 - check SS
;
;       ENTRY   As above
;       EXIT    returns if OK, prints and traps if error
;       USES    none

Procedure   SegCheck,NEAR
        ASSUME  SS:NOTHING
        SAVE    <BP>
        MOV     BP,SP                   ; set up addressing
        PUSHF                           ; Following code depends upon this order
        SAVE    <AX,BX,CX,DX,DS>        ;    "       "     "      "    "
        GETDSEG DS
        mov     dx,ds                   ; (dx) = DOSDATA segment
        mov     bx,2[bp]                ; (bx) = return address
        mov     al,cs:2[bx]             ; (al) = flag byte
        add     bx,3
        TEST    AL,1
        JZ      schk5                   ; don't check SS
        mov     cx,ss
        cmp     cx,dx
        je      schk5                   ; OK
        zfmt    <"Assumed SS invalid $S\n">,<cs,bX>
        TRAP

schk5:  test    al,2                    ; see if DS to be checked
        jz      schk10                  ; don't check DS
        mov     cx,-12[bp]
        cmp     cx,dx
        je      schk10                  ; no problem
        zfmt    <"Assumed DS invalid $S\n">,<cs,bX>
        TRAP

schk10: test    al,4                    ; see if ES to be checked
        jz      schk15                  ; don't check ES
        mov     cx,es
        cmp     cx,dx
        je      schk15                  ; no problem
        zfmt    <"Assumed ES invalid $S\n">,<cs,bX>
        TRAP

schk15: RESTORE <DS,DX,CX,BX,AX>
        POPF
        RESTORE <BP>
        ret

EndProc SegCheck


I_need  DPBHead,DWORD
I_need  BufferQueue,DWORD
I_need  sftFCB,DWORD
I_need  AuxStack,BYTE
I_need  IOStack,BYTE
I_need  renbuf,byte
I_need  CurrentPDB,WORD
I_need  User_In_AX,WORD

extrn   ECritDisk:NEAR

CritNOP label   byte
        RET

AstFrame    STRUC
Astbp       dw  ?
Astip       dw  ?
Astmes      dw  ?
Astarg      dd  ?
AstFrame    ENDS



;**     DPBCheck - Validate A DPB Pointer
;
;       DPBCheck checks to see if a supplied pointer points to a DPB
;       as it's supposed to.
;
;       ENTRY
;       EXIT    returns if OK, message and trap if error
;       USES    none

Procedure   DPBCheck,NEAR
        assume  SS:nothing
        SAVE    <BP>
        MOV     BP,SP
        PUSHF
        SAVE    <AX,BX,DS,SI,ES,DI>
        GETDSEG DS
        LES     DI,DPBHead
        LDS     SI,[BP].Astarg
    ASSUME DS:nothing
DPBLoop:CMP     DI,-1
        JZ      DPBNotFound
        invoke  PointComp
        JZ      DPBRet
        LES     DI,ES:[DI.dpb_next_dpb]
        JMP     SHORT DPBLoop

DPBNotFound:
        MOV     AX,[BP].Astmes
        zfmt    <"DPB assertion failed: $x:$x $s\n">,<ds,si,AX>
        TRAP
        JMP     SHORT $                       ; hang here

DPBRet: RESTORE <DI,ES,SI,DS,BX,AX> ;   Done:
        POPF
        RESTORE <BP>
        RET     6

EndProc DPBCheck


;**     SFTCheck - Validate an SFT Pointer
;
;       SFTCheck verifies that a pointer points to an SFT
;
;       ENTRY   BUGBUG
;       EXIT    returns if no error, traps w/message if error
;       USES    none

Procedure   SFTCheck,NEAR
        assume  SS:nothing

        SAVE    <BP>
        MOV     BP,SP
        PUSHF
        SAVE    <AX,BX,DS,SI,ES,DI>
        LDS     SI,[BP].Astarg
        XOR     BX,BX                   ;   i = 0;
SFTLoop:
        SAVE    <BX>
        invoke  SFFromSFN               ;   while ((d=SF(i)) != NULL)
        RESTORE <BX>
        JC      Sft1
        invoke  PointComp
        JZ      DPBRet                  ;               goto Done;
SFTNext:INC     BX                      ;           else
        JMP     SHORT SFTLoop                 ;               i++;


SFT1:   GETDSEG DS
        LES     DI,sftFCB
   ASSUME DS:nothing
        MOV     BX,ES:[DI.sfCount]
        LEA     DI,[DI.sfTable]
sft2:   invoke  PointComp
        JZ          DPBRet
        ADD     DI,SIZE sf_entry
        DEC     BX
        JNZ     SFT2

;       The SFT is not in the allocated tables.  See if it is one of the static
;       areas.

        GETDSEG ES
        MOV     DI,OFFSET DOSDATA:AUXSTACK - SIZE SF_ENTRY
        Invoke  PointComp
        JZ      DPBRet
        MOV     DI,OFFSET DOSDATA:RenBuf
        Invoke  PointComp
        LJZ     DPBRet


        MOV     AX,[BP].Astmes
        zfmt    <"SFT assertion failed: $x:$x $s\n">,<ds,si,AX>
        TRAP
        JMP     SHORT $                       ; hang here

EndProc SFTCheck,NoCheck


;**     BUFCheck - Validate a BUF Pointer
;
;       BUFCheck makes sure that a supposed BUF pointer is valid.
;
;       ENTRY   BUGBUG
;       EXIT    returns if OK, traps if error
;       USES    none

Procedure   BUFCheck,NEAR
        assume  SS:nothing
        SAVE    <BP>
        MOV     BP,SP
        PUSHF
        SAVE    <AX,BX,DS,SI,ES,DI>

;       CheckDisk - make sure that we are in the disk critical section...

        GETDSEG DS
        MOV     AL,BYTE PTR ECritDisk
        CMP     AL,CritNOP
        JZ      CheckDone
ifdef   NEVER           ; BUGBUG - turn this back on sometime?
        MOV     AX,CurrentPDB

        CMP     SectPDB + 2 * critDisk,AX
        MOV     AX,[BP].astmes
        JZ      CheckRef
        zfmt    <"$p: $x $s critDisk owned by $x\n">,<User_In_AX,AX,SectPDB+2*critDisk>
CheckRef:
        CMP     SectRef + 2 * critDisk,0
        JNZ     CheckDone
        zfmt    <"$p: $x $s critDisk ref count is 0\n">,<User_In_AX,AX>
ENDIF
CheckDone:

        LES     DI,BufferQueue
        LDS     SI,[BP].Astarg
  ASSUME DS:nothing
BUFLoop:CMP     DI,-1
        JZ      BufNotFound
        invoke  PointComp
        LJZ     DPBRet
        mov     di,es:buf_next[di]
        JMP     SHORT BUFLoop

BufNotFound:
        MOV     AX,[BP].Astmes
        zfmt    <"BUF assertion failed: $x:$x $s\n">,<ds,si,AX>
        TRAP
        JMP     SHORT $                       ; hang here

 DPUBLIC <DPBLoop, DPBNotFound, DPBRet>
 DPUBLIC <SFTLoop, SFTNext, SFT1, sft2, BUFLoop, BufNotFound>
 DPUBLIC <schk5, schk10, schk15>

EndProc BUFCheck,NoCheck

ENDIF

DOSCODE ENDS

        END
