;      SCCSID = @(#)qstatea.asm        6.6 91/10/18

SCCSID equ "@(#)qstatea.asm     6.6 91/10/18"
;
;         IBM/Microsoft Confidential
;
;         Copyright (c) IBM Corporation 1987, 1989
;         Copyright (c) Microsoft Corporation 1987, 1989
;
;         All Rights Reserved

TITLE   Query System State Support Routines


.xlist
include fnoperf.inc
include dosseg.inc
.xcref
include basemaca.inc
include osmaca.inc
include osconst.inc
include mi.inc
include bseerr.inc
include sem.inc
include rmp.inc
include protmode.inc
include seldesc.inc
include virtsym.inc
include qsexport.inc
.cref
.list

        ModName qstatea,FNO_QSTATEA_ASM
        CpuMode 386

        ReferGlobal     MFT_hPTree,DWORD
        ReferGlobal     SysSemRmpHdl, WORD
        ReferGlobal     SysSemDataTable, WORD
        ReferGlobal     ShareRmpStruc, WORD

        .lall
        ReferFlat       _pCurCache, DWORD
        ReferFlat       _pEndCache, DWORD
        ReferFlat       _pPtrRec, DWORD
        ReferFlat       _pRecStart, DWORD
        .xall

        EXTRN16         Rmp_FindN

        EXTRN32         _qsUpdatePtrs
        EXTRN32         _qsCheckCache
        EXTRN32         _qsFlushCache

        FARCODE HIGH32

QUERYSWAP_TEXT  SEGMENT

;**
;
;       C callable assembly language routine to grab the 16 bit
;       System Semaphore information from the global semaphore
;       table (SysSemDataTbl) and the semaphore RMP segment.
;
;       Change history:
;       ---------------
;       71325 LRN 06/28/93 - save edx reg before calling qsCheckCache.
;                            If the cache buffer is full, TKSuBuff will
;                            trash it, and we need it for the next call
;                            to Rmp_FindN.

        ASSUME  DS:FLAT, ES:FLAT, FS:NOTHING, GS:NOTHING, SS:NOTHING
Procedure _qsSys16Sem, near
LocalVar        pNextRec,DWORD          ; ptr to NextRec field
LocalVar        SaveDx,DWORD            ; 71325

        EnterProc

        SaveReg<ebx,esi,edi,ds,es>

        ; Caller made sure there is enough room in the cache for the
        ; minimum needed: 1 qsS16Headrec_t or
        ; (sizeof SysSemDataTable offset + sizeof NextRec (2 longs)

        mov     edi,_pCurCache          ; set up to grab SysSemDataTbl offset
        xor     eax,eax
        mov     ax, offset DOSGROUP:SysSemDataTable
        mov     [edi].SRecType,REC_SEMAPHORE
        mov     [edi].S16TblOff,eax     ; store SysSemDataTable offset
        mov     [edi].S32SemRec,0
        mov     [edi].SpNextRec,0
        add     edi, offset pSem16Rec   ; in S16TblOff field of header structure
        mov     pNextRec, edi           ; store ptr to nextrec field
        push    edi
        CCALL32 _qsUpdatePtrs           ; update buffer and cache pointers

        ; Set registers for call to Rmp_FindN to grab Semaphore Rmp record

        xor     edx,edx         ; start search at beginning of segment
        xor     eax,eax         ; consider first record found
        xor     ebx,ebx         ; no offset since not using a pattern
s16_1:  xor     ecx,ecx         ; no match pattern, get next record

        DosContext es
        mov     di,offset DOSGROUP:SysSemRmpHdl ; -> RMP seg handle

        CALL16  Rmp_FindN
        jc      s16_done        ; 71325 removed "short" specification

        ; ES:DI -> a record in RMP system semaphore segment
        ; CX = size of the RMP record

        movzx   ecx,cx          ; convert returned size
        movzx   edi,di          ; and offset
        mov     edx,edi         ; save offset for next call to Rmp_FindN

        ; copy the global sem table record corresponding to this RMP record
        ; to user buffer at pNextRec

        SaveReg <ecx,edi,es>

        ; make sure record will fit into buffer cache
        add     ecx,size NextRec ; size of rmp record + pointer to next rec
        add     ecx,size SysSemTblStruc ; + size of SysSemTblStruc
        add     ecx, 2           ; pad size short for dword aligned struct
        mov     SaveDx,edx      ; 71325 save, or TKSuBuff will clobber
        push    es              ; save es (178) used for 16 bit code    7/11/91
        push    ecx
        FlatContext es          ; change es  (168) used for 32 bit code 7/11/91
        push    ecx
        CCALL32 _qsCheckCache   ; see if this record will fit into cache
        pop     ecx
        or      eax,eax         ; if eax == NO_ERROR
        jz      short s16_2     ; jmp
        add     esp,16          ; clear off stack
        jmp     short s16_err   ; exit with error

        ; set up source pointers for movsb
s16_2:  pop     es              ; change es back (178) used for 16 bit code 7/11/91
        mov     edx,SaveDx      ; 71325
        mov     si,es:[di]                      ; ES:DI->entry in sys sem tbl
        movzx   esi,si                          ; clear high word
        mov     edi,_pCurCache
        add     ecx,_pRecStart
        mov     [edi],ecx                       ; store offset to next record
        add     edi, size NextRec               ; and skip past it for copy
        mov     ecx, size SysSemTblStruc

        DosContext  <ds>
        FlatContext <es>

        ; DS:SI -> entry in the global semaphore table corresponding to RMP rec
        ; ES:DI -> cache

        rep     movsb
        add     edi, 2  ; BUG pad size short for dword aligned structure

        RestoreReg <ds,esi,ecx>
        ; DS:SI -> entry in the RMP semaphore segment
        ; ES:DI -> cache
        ; ECX = sizeof rmp record

        rep     movsb

        FlatContext <ds>

        push    edi
        CCALL32 _qsUpdatePtrs           ; update buffer and cache pointers
        mov     edi,_pCurCache          ; store ptr to nextrec field
        mov     pNextRec, edi           ; store ptr to nextrec field

        ; prepare for next call to Rmp_FindN
        mov     al,1                    ; do not consider record at DX
        jmp     s16_1                   ; DX = offset to start search

s16_done:
        xor     eax,eax                 ; return NO_ERROR
s16_err:
        clc
        SaveReg<eax>                    ; save return value
        FlatContext es                  ; 75959 end marker = 4 bytes of zero
        push    4                       ; 75959 see if end marker will fit into
        CCALL32 _qsCheckCache           ; 75959     cache....
        or      eax,eax                 ; 75959 Check Return Code
        jz      @F                      ;; 78162 - branch on no overflow
        RestoreReg<ebx>                 ;; 78162 - remove old eax (garbage)
        SaveReg<eax>                    ;; 78162 - .. to be Restore'd below
        jmp     s16_out                 ;; 78162 - out on error
@@:                                     ;; 78162 - here on success
;;      jnz     short s16_out           ; 75959 exit if there's not 4 bytes left
;;                                      ; 75959      in user buffer.

        mov     eax,QS_END
        mov     edi,_pCurCache          ; 75959   reset edi to _pcurcache
                                        ; 75959   in case kernel cache data was
                                        ; 75959   moved to user buffer. If this
                                        ; 75959   happens then _pcurcache is
                                        ; 75959   reset to _pbegincache .
        mov     [edi],eax               ; mark end of records
        add     edi, 4                  ; 75959 and skip past end marker
        push    edi
        CCALL32 _qsUpdatePtrs           ; update buffer and cache pointers
;;      RestoreReg <eax>                ; crs

s16_out:                                ; 75959 jump here if user buffer full.
                                        ; 75959   if so then eax != 0.
        RestoreReg <eax>                ; crs
        RestoreReg <es,ds,edi,esi,ebx>
        LeaveProc
        RETP

EndProc _qsSys16Sem

;**
;
;       C callable assembly language routine to grab
;       the shared memory RMP segment for the given process.
;
        ASSUME  DS:FLAT, ES:FLAT, FS:NOTHING, GS:NOTHING, SS:NOTHING
Procedure _qs16ShrMem, near
ArgVar          pSMemRec,DWORD
ArgVar          ptdahandle,WORD ; ptda_handle for this ptda
LocalVar        pEndCache,DWORD ; = _pEndCache to avoid ds reloading in loop
LocalVar        cShrMem,WORD    ; # shared mem handles found for this proc

        EnterProc

        SaveReg<ebx,esi,edi,ds,es>

        ; Set registers for call to Rmp_FindN to grab Shared Memory Rmp record

        xor     edx,edx                 ; start search at beginning of segment
        xor     eax,eax                 ; consider first record found
        mov     edi,_pEndCache          ; store this locally to avoid restoring
        mov     [pEndCache],edi         ; ds in the loop
        mov     cShrMem,0               ; initialize count

        push    [ptdahandle]
        push    ss                      ; (DS:SI) points to match pattern
        pop     ds
        mov     si,sp

smem_1: mov     bx,offset lsm_ptda      ; bx=offset of match pattern
        mov     cx,2                    ; cx=no. of bytes to be matched

        DosContext <es>
        mov     di,offset DOSGROUP:ShareRmpStruc     ; -> RMP seg handle

        CALL16  Rmp_FindN
        jc      short smem_done
        mov     ax, es:[di].lsm_seghandle       ; AX = shared segment handle
        mov     dx, di                  ; start of next search
        FlatContext <es>

        mov     edi,pSMemRec            ; ES:EDI -> user buffer
        cmp     edi,pEndCache           ; will entry fit into cache?
        jge     short smem_3            ; no, flush and reset ptrs

smem_2: stosw                           ; put table entry into user buffer
        mov     pSMemRec,edi            ; and update buffer pointer
        inc     [cShrMem]               ; update number of entries found
        mov     al, 1                   ; don't consider record at dx
        jmp     short smem_1            ; look for another record

smem_3: push    edi                     ; Cache is full
        CCALL32 _qsUpdatePtrs           ; update buffer and cache pointers
        CCALL32 _qsFlushCache           ; FlushCache and reset ptr
        mov     edi,_pCurCache          ; reset pSMemRec
        or      eax,eax                 ; if eax == NO_ERROR
        je      short smem_2            ; put info in cache
        jmp     short smem_err          ; else exit with error

smem_done:
        xor     eax,eax                 ; return NO_ERROR
smem_err:
        clc
        FlatContext <ds>
        pop     cx                      ; take ptda_handle off of stack
        mov     edi,pSMemRec            ;
        movzx   esi,cShrMem
        mov     [edi],esi               ; pass back count of handles in cache
        SaveReg<eax>                    ; save error code for return
        push    edi
        CCALL32 _qsUpdatePtrs           ; update buffer and cache pointers

        RestoreReg<eax,es,ds,edi,esi,ebx>
        LeaveProc
        RETP

EndProc _qs16ShrMem


;***LP  qsMemory- Copy shared memory information into buffer
;
;       ulong_t qsMemory (level, pid)
;
;       C callable assembly language routine to grab the 16 bit
;       System Shared Memory information from the shared memory RMP segment.
;
;       ENTRY   level   - Level of information requested
;
;       EXIT    ulong_t - Standard error code
;
;       MODIFIES        pCurCache
;
;       Change history:
;       ---------------
;       71325 LRN 06/28/93 - save edx reg before calling qsCheckCache.
;                            If the cache buffer is full, TKSuBuff will
;                            trash it, and we need it for the next call
;                            to Rmp_FindN.
;

        ASSUME  DS:FLAT, ES:FLAT, FS:NOTHING, GS:NOTHING, SS:NOTHING
Procedure _qsMemory, near
ArgVar          level,DWORD
ArgVar          pid,DWORD
LocalVar        cShMem,WORD
LocalVar        pNextRec,DWORD ;ptr to NextRec field
LocalVar        RmpRecSz,DWORD    ;9/25/91 to remove savereg <ecx>
LocalVar        RRecSz,DWORD      ;9/25/91 to remove savereg <ecx>
LocalVar        SaveDx,DWORD      ; 71325

        EnterProc

        SaveReg<ebx,esi,edi,ebp,ds,es>    ;9/25/91 removed ss,esp

        ; Set registers for call to Rmp_FindN to grab Shared Memory Rmp record

        mov     edi,_pCurCache
        mov     pNextRec,edi
        mov     cShMem,0
        xor     edx,edx                 ; start search at beginning of segment
        xor     eax,eax                 ; consider first record found
        xor     ebx,ebx                 ; no offset since not using a pattern
mem_1:  xor     ecx,ecx                 ; no match pattern, get next record

        DosContext es
        mov     di,offset DOSGROUP:ShareRmpStruc     ; -> RMP seg handle

        CALL16  Rmp_FindN
        jc      short mem_done

        ; ES:DI -> a record in RMP shared memory segment
        ; CX = size of the RMP record

        movzx   edi,di          ; offset into RMP of record
        mov     edx,edi         ; save offset for next call to Rmp_FindN
        cmp     cx, size lsm_s  ; is this a local record?
        jle     short mem_2     ; yes, skip it
        inc     cShMem          ; increment count of shared memory records
        movzx   ecx,cx          ; convert returned size

        mov     RmpRecSz,ecx    ;SaveReg <ecx> 9/25/91
        ; make sure record will fit into buffer cache
        add     ecx,size MemNextRec ; size of rmp record + pointer to next rec
        mov     RRecSz,ecx      ;SaveReg <ecx> 9/25/91
        mov     SaveDx,edx      ; 71325 - save, or TKSuBuff will clobber
        SaveReg <es>            ; save es (178) used for 16 bit code  7/11/91
        FlatContext es          ; change es (168) used for 32 bit code 7/11/91
        push    ecx
        CCALL32 _qsCheckCache   ; see if this record will fit into cache
        RestoreReg <es>         ; change es back (178) used for 16 bit code 7/11/91
        mov     edx,SaveDx      ; 71325
        or      eax,eax         ; if eax != NO_ERROR
        jne     short mem_err   ; exit with error

        mov     esi,edi         ; set up source for rep movsb
        mov     ecx,RRecSz      ;RestoreReg <ecx> 9/25/91
        mov     edi,_pCurCache
        add     ecx,_pRecStart
        mov     [edi],ecx       ; store offset of pNextRec field
        add     edi,size MemNextRec ; skip offset field
        push    es
        pop     ds
        FlatContext es
        ; ES:DI -> cache
        ; DS:SI -> a record in RMP shared memory segment
        mov     ecx,RmpRecSz    ;RestoreReg <ecx>  9/25/91
        rep     movsb           ; store record in cache
        FlatContext ds

        push    edi
        CCALL32 _qsUpdatePtrs   ; update buffer and cache pointers
        mov     edi,_pCurCache  ; store ptr to nextrec field
        mov     pNextRec, edi   ; store ptr to nextrec field

        ; prepare for next call to Rmp_FindN
mem_2:  mov     al,1            ; do not consider record at DX
        jmp     mem_1           ; DX = offset to start search
                                ; 71325 removed "short" specification

mem_done:
        xor     eax,eax         ; return NO_ERROR
mem_err:
        SaveReg <eax>               ; crs
        clc
        cmp     cShMem,0        ; if there are no system shared mem recs
        je      mem_none
        FlatContext es              ; 75959
;;      SaveReg <eax>               ; 75959 save return value - crs
        push    4                   ; 75959 end marker = 4 bytes of zeroes
        CCALL32 _qsCheckCache       ; 75959 see if end marker will fit into
                                    ; 75959    remaining space in user buffer.
        or      eax,eax             ; 75959 Check return code.
        jz      @F                  ;; 78162 - branch on no overflow
        RestoreReg<ebx>             ;; 78162 - remove old eax (garbage)
        SaveReg<eax>                ;; 78162 - .. to be Restore'd below
        jmp     mem_out             ;; 78162 - out on error
@@:                                 ;; 78162 - here on success

;;      jnz     short mem_out       ; 75959 If non-zero, marker couldn't fit.

        mov     eax,QS_END
        mov     edi,_pCurCache      ; 75959   set edi to _pcurcache
                                    ; 75959   in case kernel cache data was
                                    ; 75959   moved to user buffer. If this
                                    ; 75959   happens then _pcurcache is
                                    ; 75959   reset to _pbegincache .
        mov     [edi],eax       ; mark end of records
        add     edi, 4              ; 75959 and update ptr past end marker
        push    edi
        CCALL32 _qsUpdatePtrs   ; update buffer and cache pointers
;;      RestoreReg <eax>        ; restore return value
        jmp     short mem_out
mem_none:
        mov     edi,_pPtrRec    ; set pPtrRec->pMemRec =  QS_END
        mov     [edi].pMemRec,QS_END
mem_out:
        RestoreReg <eax>        ; restore return value - crs
        RestoreReg<es,ds,ebp,edi,esi,ebx>  ;removed esp,ss 9/25/91
        LeaveProc
        RETP

EndProc _qsMemory

QUERYSWAP_TEXT  ends
        end
