;       SCCSID = @(#)ldrrsrc.asm        6.19 92/03/29
SCCSID  equ     "@(#)ldrrsrc.asm        6.19 92/03/29"
        PAGE    ,132
TITLE   LDRRSRC - OS/2 2.x loader resource functions
NAME    LDRRSRC


;***    OS/2 2.0 resource routines
;
;        IBM/Microsoft Confidential
;
;        Copyright (c) IBM Corporation 1987, 1989
;        Copyright (c) Microsoft Corporation 1987, 1989
;
;        All Rights Reserved


.XLIST
        INCLUDE dosseg.inc
        INCLUDE basemaca.inc
        INCLUDE osmaca.inc
        INCLUDE fnomem.inc
        INCLUDE osconst.inc
        INCLUDE mi.inc
        INCLUDE error.inc
        INCLUDE protmode.inc
        INCLUDE seldesc.inc
        INCLUDE dossymc.inc
        INCLUDE sigdef.inc
        INCLUDE except.inc
        INCLUDE pgexport.inc
        INCLUDE vmexport.inc
        INCLUDE selxport.inc
        INCLUDE vmowner.inc
        INCLUDE tkexport.inc
        INCLUDE infoseg.inc
        INCLUDE curdir.inc
        INCLUDE dirent.inc
        INCLUDE find.inc
        INCLUDE screen.inc
        INCLUDE sem.inc
        INCLUDE tkptda.inc
        INCLUDE ldrvars.inc
        INCLUDE ldrxport.inc
        INCLUDE dynxport.inc
        INCLUDE virtsym.inc
.LIST
        CpuMode 386
        ModName ,FNO_LDRRSRC_ASM

        ReferFlat       _swapping,DWORD
        ReferFlat       _pPTDACur,DWORD
        ReferFlat       RsrcHead,DWORD

        EXTRN           Bmp_Get:near
        EXTRN           w_FreeSeg:near

        EXTRN16         Bmp_Free

        EXTRN32         _LDRGetSegment
        EXTRN32         _SELGetDescInfo
        EXTRN32         _SELClearPreload
        EXTRN32         _VMGetPTDAAddr
        EXTRN32         _ldrAllocSegment
        EXTRN32         _ldrGetResource
        EXTRN32         _ldrFindObject
        EXTRN32         _SELGetOd
        EXTRN32         _ldrASMpMTEFromHandle
        EXTRN32         _ldrBlastResource
        EXTRN32         _LDRClearSem
        EXTRN32         _KSEMRequestMutex

        EXTRNF32        _LDRClearSem

        FARCODE HIGH2
HIGH2CODE SEGMENT


;**     ldrIncRefCount - increment reference count for a resource selector
;
;       ENTRY   (EBX) = resource TypeId
;               (ECX) = resource NameId
;               (EDX) = mte handle
;               (EDI) = pointer to mte
;
;       EXIT    CY clear
;                 Success
;               CY set
;                 (AX) = Error Code
;
;       USES    EAX,ESI,FLAGS
;
;       PSEUDOCODE
;
;       If (new)
;         ldrRsrcAlloc (rsrc_typeid, rsrc_nameid, owner);
;       else
;         RsrcFindLocal (rsrc_typeid, rsrc_nameid, owner);
;       if !(error)
;         rsrc_refcount++;

        ASSUME DS:FLAT, ES:FLAT, FS:NOTHING, GS:NOTHING, SS:NOTHING

Procedure ldrIncRefCount,<far16,hybrid>

        push    es                      ; (ES)  = FLAT
        push    edi                     ; (EDI) = pointer to mte

        mov     eax,_pPTDACur
        mov     eax,[eax].pPTDAExecChild
        or      eax,eax
        jnz     short irc1
        mov     eax,_pPTDACur
irc1:   les     di,[eax].ptda_rsrclist  ; (ES:DI) = rsrc list
        ASSUME  ES:NOTHING

; (cy,es:di->bmprec) = RsrcFindLocal(ebx=typeid,ecx=nameid,dx=hmte,es:di->rsrc)

        CALLF32 RsrcFindLocal,,nocheck  ; find the record
        jc      short ircie1            ; record not found

        inc     es:[di].rsrc_refcount   ; increment reference count
        jz      short ircie2

irc12:  xor     eax,eax                 ; success
       ;clc                               xor clears the carry

ircx:   pop     edi                     ; (EDI) = pointer to mte
        pop     es                      ; (ES)  = FLAT
        RETC

ircie1: mov     eax,ERROR_INVALID_HANDLE
        stc
        jmp     short ircx

ircie2: mov     eax,ERROR_NOT_ENOUGH_MEMORY
        dec     es:[di].rsrc_refcount
        stc
        jmp     short ircx

EndProc ldrIncRefCount


HIGH2CODE ENDS



        FARCODE HIGH3
HIGH3CODE SEGMENT

;**     w_getresource - get the selector to a resource segment
;
;       This routine returns the segment selector associated with
;       the passed Type/Name ID in the passed module.
;
;       ENTRY   (AX)    = Type ID
;               (DX)    = Name ID
;               (SI)    = handle of module which contains the resource segment
;               (BX)    = 0 if called from DosGetResource
;                         1 if called from DosGetResource2
;
;       EXIT    CARRY Clear on Success
;                 (AX) = Selector of resource segment
;                 (DX) = Offset of resource
;               CARRY Set on Error
;                 (AX) = Error Code
;
;       USES    EAX,EBX,ECX,EDX,ESI,EDI,DS,ES,FLAGS

        ASSUME DS:NOTHING, ES:NOTHING, FS:NOTHING, GS:NOTHING, SS:NOTHING

Procedure w_getresource,<faronly>
        LocalVar        addr,<size ldrrrsrc_t>

        EnterProc ,,alignesp

        FlatContext     <ds,es>,cx
        mov     ecx,LDR_16bit           ; assume called from DosGetResource
        or      bx,bx                   ; check if called from DosGetresource
        jz      short wgrsa
        mov     ecx,LDR_32bit           ; called from 32-bit module

;       rc = ldrGetResource(typeid, nameid, hob, prrsrc, ldrtype)

wgrsa:  PushP   ecx                     ; ldrtype
        SSToDS  ebx,[addr]              ; prrsrc
        PushP   ebx                     ; place to return resource address
        movzx   ebx,si                  ; hob
        movzx   edx,dx                  ; name id
        movzx   eax,ax                  ; type id
        CCALL32 _ldrGetResource,<eax,edx,ebx>,,PushP
        or      eax,eax
        stc                             ; assume error
        jnz     short wgr1

        clc                             ; no error
        mov     dx,word ptr [addr].ldrrrsrc_ptr         ; return offset
        cmp     [addr].ldrrrsrc_type,LDR_16bit
        jne     short wgr2
        mov     ax,word ptr [addr+2].ldrrrsrc_ptr       ; return sel
        jmp     short wgr1

wgr2:   mov     eax,dword ptr [addr].ldrrrsrc_ptr       ; Convert to Sel (AX)
        ; ok to use tiled version as resources are not packed
        LaToSelTiled eax

wgr1:   LeaveProc
        ret

EndProc w_getresource




;***LP  GetRsrcSel - get the selector to the resource segment
;
;       This routine returns the segment selector associated with
;       the passed segment number
;
;       ENTRY   (EAX) = Segment Number
;               (BX) = Resource TypeId
;               (CX) = Resource NameId
;               (DX) = module table entry handle
;               (EDI) -> mte pointer
;
;       EXIT    CARRY Clear on Success
;                 (AX) = Selector of resource segment
;               CARRY Set on Error
;                 (AX) = Error Code
;
;       USES    EAX,EBX,ECX,EDX,EDI,ESI,FLAGS
;
;

        ASSUME DS:FLAT, ES:FLAT, FS:NOTHING, GS:NOTHING, SS:NOTHING

Procedure GetRsrcSel,far16

        LocalVar        <grs_segno>,DWORD
        LocalVar        <grs_mteptr>,DWORD
        LocalVar        <grs_rsrctypeid>,WORD
        LocalVar        <grs_rsrcnameid>,WORD
        LocalVar        <grs_mtehndl>,WORD
        LocalVar        <grs_hugecnt>,WORD
        LocalVar        <grs_steptr>,DWORD
        LocalVar        grs_seldesc,<SIZE seldesc_s>

        EnterProc       <eax,edi,bx,cx,dx>

        dec     eax                     ; (EAX) seg number make zero based
        mov     ecx,[edi].mte_swapmte   ; (ECX) swappable mte
        mov     esi,[ecx].smte_objtab   ; get ste pointer
        mov     ecx,SIZE ldrste_s
        imul    eax,ecx
        add     eax,esi
        mov     [grs_steptr],eax        ; save pointer to ste

;       (cy,cx=cnt)=IsHugeRsrc(ax=segno,bx=typeid,cx=nameid,edi=mteptr,
;                              esi=steptr)

        xchg    esi,eax                 ; (ESI) = pointer to ste
        mov     eax,[grs_segno]         ; (EAX) = segment number
        mov     cx,[grs_rsrcnameid]     ; (CX) = name id
        CALLF32 IsHugeRsrc              ; is this the base of a huge rsrc seg?
        mov     [grs_hugecnt],cx        ; save number of segments

;       We have one of the following:
;       - ste_seghdl is zero; need to allocate the segment (and the selector)
;       - ste_seghdl & ste_selector are non-zero but ste_selector is not
;         attached to the process; need to attach
;
        mov     eax,[grs_segno]         ; (AX) = segment number

grs12:  push    cx                      ; (CX) = number of segments in the rsrc
        push    eax                     ; segment number

        mov     ecx,TRUE                ; Force load of resource

;       rc = ldrAllocSegment(pmte, pste, iseg, 1)

        CCALL32 _ldrAllocSegment, <edi,esi,eax,ecx>
        or      eax,eax
        je      short grs14

        stc                             ; set carry to indicate error
        jmp     grsx

grs14:  pop     eax                     ; (EAX) = segment number
        pop     cx                      ; (CX) = number of segments in the rsrc
        inc     eax                     ; next segment
        add     esi,SIZE ldrste_s       ; point to next segment entry
        loop    grs12

;       if swapping is off, force the resource segment(s) to be loaded

        cmp     _swapping,0             ; are we swapping?
        jne     grs16                   ; jump if we are

        SSToDS  eax,[grs_seldesc]

        PushP   eax                     ; return buffer
        mov     eax,[_pPTDACur]
        mov     eax,[eax].pPTDAExecChild
        or      eax,eax
        jnz     short grs14a
        mov     eax,_pPTDACur
grs14a: movzx   eax,word ptr [eax].ptda_handle
        PushP   eax                     ; ptda handle
        mov     esi,[grs_steptr]        ; (ESI) = pointer to ste
        movzx   ebx,[esi].ste_selector  ; (BX) = resource selector
        PushP   ebx                     ; selector

;       rc = SELGetDescInfo(sel, hptda, pseldesc)

        CCALL32 _SELGetDescInfo,,,PushP
        or      eax,eax
        jne     short grsx

        test    [grs_seldesc].desc_acc,D_PRES
        jnz     short grs16

;       Clear the preload flag:
;       void SELClearPreload(sel, hptda)

        mov     eax,[_pPTDACur]
        mov     eax,[eax].pPTDAExecChild
        or      eax,eax
        jnz     short grs14b
        mov     eax,_pPTDACur
grs14b: movzx   eax,[eax].ptda_handle
        CCALL32 _SELClearPreload,<ebx,eax>

        movzx   ecx,[grs_hugecnt]       ; (CX) = number of seg in this rsrc

;       (eax=err) = RsrcPreload (bx=sel,cx=hugecnt,edi=mteptr)

        call    RsrcPreload             ; force the preloading of the resource
        or      eax,eax
        jne     short grsx              ; jump if error

grs16:  movzx   ebx,[grs_rsrctypeid]
        movzx   ecx,[grs_rsrcnameid]
        movzx   edx,[grs_mtehndl]

;       (cy,ax=err) = ldrIncRefCount (ax=flags,bx=typeid,cx=nameid,
;                                  dx=mtehdl,edi=mteptr)

        CALLFAR ldrIncRefCount
        jc      short grsx              ; jump if error

        mov     esi,[grs_steptr]
        mov     ax,[esi].ste_selector   ; (AX) = resource selector
        clc

grsx:   pushf                           ; save CARRY flag
        mov     esi,[grs_steptr]
        popf                            ; restore CARRY flag
        LeaveProc
        RETC

EndProc GetRsrcSel




;**     RsrcPreload - preload the passed in resource
;
;       ENTRY   (EBX) = resource selector
;               (ECX) = count of consecutive resource selectors
;               (EDI) = pointer to mte
;
;       EXIT    (EAX) = NO_ERROR
;               or
;               (EAX) = error code
;
;       USES    EAX,ECX,EDX,FLAGS

        ASSUME DS:FLAT, ES:FLAT, FS:NOTHING, GS:NOTHING, SS:NOTHING

Procedure RsrcPreload,near,local
        push    ecx
        PushP   ebx                     ; sel
        shl     ebx,SEL_LADDR_SHIFT     ; convert selector to address
        and     ebx,SEL_LADDR_MASK
        PushP   ebx                     ; ebx = linear address of object
        movzx   ebx,word ptr [edi].mte_handle
        PushP   ebx                     ; (bx) = mte handle

;       rc = LDRGetSegment(hobmte, laddr, sel)

        CCALL32 _LDRGetSegment,,,PushP
        or      eax,eax
        jnz     short rplx
        add     ebx,HUGEINCR            ; next resource selector
        pop     ecx
        loop    RsrcPreload

        xor     eax,eax                 ; return NO_ERROR
rplx:   ret

EndProc RsrcPreload



;*      ldrRsrcAlloc - Allocate a new BMP entry for a resource segment
;
;       Allocates a new BMP record, fills in id and owner field,
;       sets ref count to 0, and links onto global and local lists.
;
;       The structure of this BMP record is as follows:
;       rsrc_s struc
;         rsrc_typeid    dd     0       ; resource type id
;         rsrc_nameid    dd     0       ; resource name id
;         rsrc_mte       dw     0       ; owner
;         rsrc_refcount  dw     0       ; local reference count
;         rsrc_localptr  dw     0       ; local PTDA chain
;         rsrc_globalptr dw     0       ; global chain
;       rsrc_s ends
;
;       ENTRY:  (AX) = ptda_child
;               (EBX) = Resource Type Id
;               (ECX) = Resource Name Id
;               (DX) = Owner
;
;       EXIT:   CY clear
;                 new BMP record allocated
;               CY set
;                 allocation failed
;
;       USES:   AX,DI,SI,Flags
;               ES,DS Preserved

        ASSUME DS:FLAT, ES:NOTHING, FS:NOTHING, GS:NOTHING, SS:NOTHING

Procedure ldrRsrcAlloc,<near,far16>

        SaveReg <ds,es>

        mov     es,[RsrcHead].Segmt     ; address of the BMP segment

;       (cy,di=recoffset) = Bmp_Get(es=bmpsel)

        push    ebx                     ; (EBX) Type ID
        push    ecx                     ; (ECX) Name ID
        call    Bmp_Get
        pop     ecx                     ; (ECX) Name ID
        pop     ebx                     ; (EBX) Type ID
        jc      short ra4               ; return error

        mov     es:[di].rsrc_typeid,ebx ; install Type ID
        mov     es:[di].rsrc_nameid,ecx ; install Name ID
        mov     es:[di].rsrc_mte,dx     ; install owner
        xor     si,si
        mov     es:[di].rsrc_refcount,si; init refcount

;       Attach to global list

        mov     si,[RsrcHead].Offst
        mov     es:[di].rsrc_globalptr,si
        mov     [RsrcHead].Offst,di

;       Attach to local list

        push    es                              ; (ES) = selector of BMP segment
        movzx   eax,ax
        FlatContext <ds,es>

;       pptda = VMGetPTDAAddr(hobptda)

        CCALL32 _VMGetPTDAAddr,<eax>
        pop     es                              ; (ES) = selector of BMP segment
    assume es:nothing
        mov     si,[eax].ptda_rsrclist.Offst
        mov     es:[di].rsrc_localptr,si
        mov     [eax].ptda_rsrclist.Offst,di

        xor     ax,ax                   ; no_error
        clc                             ; indicate success
        jmp     short rax

ra4:    mov     ax,ERROR_NOT_ENOUGH_MEMORY      ; Bmp_Get failed
rax:    RestoreReg <es,ds>
        ret
EndProc ldrRsrcAlloc




;**     w_FreeResource - Free the selector to a resource segment
;
;       ENTRY   (AX)    = Selector
;
;       EXIT    CARRY Clear on Success
;
;       USES    EAX,FLAGS

        ASSUME DS:NOTHING, ES:NOTHING, FS:NOTHING, GS:NOTHING, SS:NOTHING

Procedure w_FreeResource,<faronly>

SEL_FREEFLAGS equ (VMGS_SLOCKWAIT or VMGS_VERIFY)
SEL_FREEFLAGS2 equ (VMGS_SLOCKWAIT or VMGS_VERIFY or VMOD_ANY_CTXT)

        LocalVar wfs_seldesc,<size seldesc_s>
        LocalVar wfs_od,<size vmod_s>

        EnterProc

        FlatContext <ds,es>,cx

        ; get the kernel semaphore
        push    eax
        mov     ebx, [_pPTDACur]
        lea     eax,[ebx].ptda_ptdasem
        CCALL32 _KSEMRequestMutex,<eax,-1>
        pop     ebx
        or      eax,eax
        jnz     wfrx2

        ; Get the loader semaphore
        push    ebx
        LDRGetSem
        pop     ebx
        or      eax,eax
        jnz     wfrx1                           ; Error from _LDRGetSem()

        ; verify the selector was valid to start with, and get the hMTE
        ; _SELGetOd (fl, sel, &seldesc_s, &vmod_s)
        SSToDS  esi,wfs_od
        SSToDS  edi,wfs_seldesc
        xor     edx,edx
        mov     wfs_od.od_pPTDA,edx                     ; current PTDA
        movzx   eax,bx
        push    eax                                     ; save the selector
        CCALL32 _SELGetOd <SEL_FREEFLAGS, eax, edi, esi>
        or      eax,eax
        jnz     short wfr_x
        pop     eax                                     ; retrieve the selector
        mov     esi,[wfs_od].od_pob                     ; find the hMTE
        movzx   ebx,[esi].ob_hobmte
        mov     esi,[wfs_od].od_laddr                   ; find the v addr

        ; decrement useage count, free if goes to 0
        push    eax                                    ; save the sel
        push    esi                                    ; save the laddr
        push    ebx                                    ; save the hMTE
        call    w_FreeSeg                              ; expects sel in ax
        pop     ebx                                    ; retrieve hMTE
        pop     esi                                    ; retrieve the laddr
        or      ax,ax
        jnz     short wfr_x

        ; check see if the selector is still valid
        ; _SELGetOd (fl, sel, &seldesc_s, &vmod_s)
        pop     edi                                    ; retrieve sel
        SSToDS  eax,wfs_od
        SSToDS  ecx,wfs_seldesc
        xor     edx,edx
        mov     wfs_od.od_pPTDA,edx
        push    esi                                    ; save the laddr
        push    ebx                                    ; save the hMTE
        CCALL32 _SELGetOd <SEL_FREEFLAGS2, edi, ecx, eax>
        pop     ebx                                    ; retrieve the hMTE
        or      eax,eax
        jz      short wfr_x        ; selector still valid - exit as all done

        ; need to zero out the fields in the STE so that allocate knows the
        ; segment is gone - find the pMTE
        CCALL32 _ldrASMpMTEFromHandle <ebx>  ; returns eax=pMTE

        pop     esi             ; retrieve the v addr
        push    ecx             ; line up stack for exit

        CCALL32 _ldrBlastResource <eax,esi>
wfrpx:  xor     eax,eax

wfr_x:  pop     ebx              ; restore the stack
        mov     ebx,eax                         ; clear the loader semaphore,
        CCALL32 _LDRClearSem                    ; but preserve the error code
        mov     eax,ebx                         ; we already have in eax

wfrx1:
        mov     ebx,eax                         ; save RC
        mov     edx,[_pPTDACur]
        lea     eax,[edx].ptda_ptdasem
        CCALL32 _KSEMReleaseMutex,<eax>
        mov     eax,ebx                         ; retrieve RC

wfrx2:  clc
        or      eax,eax
        jz      short wfrxx
        stc                                     ; return c on error
wfrxx:
        LeaveProc
        ret

EndProc w_FreeResource




HIGH3CODE ENDS

        FARCODE HIGH32
HIGH32CODE      SEGMENT

;***LP  ldrGetRsrcTypeName - if a resource seg, get its Type and Name ID's
;
;       ENTRY   (EAX)   = pointer to rsrc list
;               (BX)    = segment number
;               (EDI)   = mte pointer
;
;       EXIT    CY clear
;                 (EBX) = resource Type ID
;                 (ECX) = resource Name ID
;               CY set
;                 Not a resource (error code not returned)
;
;       USES    EAX,EBX,ECX,FLAGS
;
;       PSEUDOCODE
;
;       if (segment is a resource)
;         {set EBX=TypeId, ECX=NameId;
;          clear CY
;          return}
;       else
;         {set CY                       /* segment is not a resource */
;          return}


        assume ds:FLAT, es:FLAT, fs:nothing, gs:nothing, ss:nothing
Procedure ldrGetRsrcTypeName,near

        push    edx                     ; (EDX) = mte handle
        push    esi                     ; (ESI) = pointer to ste

        mov     dx,word ptr [edi]     ; check for 32-bit module
        and     dx,MTEFORMATMASK
        cmp     dx,MTEFORMATLX
        jne     short grtn1           ; go to 16-bit handler

; For 32-bit modules the nameid is equal to the object number and the
; type id is equal to -1. The reason is that resources are packed for
; 32-bit modules.  So the resource count is for the whole object.
; Search the local resource list to see if this is a resource

        ; does a resource list exist ?
        or      eax,eax
        jz      short grtne1             ; no - bail out

        ; is this object a resource object ?
        mov     esi,[edi].mte_swapmte
        mov     esi,[esi].smte_objtab    ; base of the object table
        mov     ecx,SIZE ldrote_s
        movzx   ebx,bx
        dec     ebx                      ; need to zero base index
        imul    ecx,ebx
        inc     ebx
        add     esi,ecx                  ; index into the object table
        mov     ecx,[esi].ote_flags      ; get the flags for this object
        and     cx,OBJRSRC
        jz      short grtne1            ; not a resource object - bail out

        push    edi                     ; (EDI) = mte pointer
        push    es                      ; (ES) = Flat
        movzx   ecx,bx                  ; (ECX) nameid
        mov     ebx,0ffffffffh          ; (EBX) typeid
        mov     dx,[edi].mte_handle     ; (DX) mte handle
        mov     di,ax
        shr     eax,16
        mov     es,eax                  ; (ES:DI) = rsrc list
        CCALL32 RsrcFindLocal
        pop     es                      ; (ES) = Flat
        pop     edi                     ; (EDI) = mte pointer

grtnx:  pop     esi                     ; (ESI) = pointer ste
        pop     edx                     ; (EDX) = mte handle
        RETC


grtne1: stc                             ; set error flag and get out
        jmp     short grtnx


grtn1:  ; 16-bit handler

        mov     ecx,[edi].mte_swapmte   ; (ECX) = swappable mte
        mov     eax,[ecx].smte_objcnt   ; (EAX) = total number of segments
        sub     eax,[ecx].smte_rsrccnt  ; (EAX) = number of non-rsrc segments
        cmp     bx,ax                   ; is this a resource segment
        jbe     short grtne1            ;  yes, get its Type and Name ID's
                                        ;  no, bail out

;       (BX) = segment number
;       (EDI) -> mte pointer

        mov     esi,[ecx].smte_rsrctab
        sub     bx,ax                   ; (BX) = seg number within resrc table
        dec     bx
        mov     eax,SIZE ldrrsrc16_t
        mul     bx                      ; compute index to resource
        add     esi,eax                 ; add to start of resource table
        movzx   ecx,[esi].ldrrsrc16_name; (ECX) = NameId
        movzx   ebx,[esi].ldrrsrc16_type; (EBX) = TypeId
        clc
        jmp     short grtnx

EndProc ldrGetRsrcTypeName



;***LP  ldrIsBaseRsrc - Check if segment is the base of a rsrc segment
;
;       This routine determines if the segment is the base segment of a
;       resource.
;
;       ENTRY   (AX) = segment number
;               (EBX) = Resource Type Id
;               (ECX) = Resource Name Id
;               (EDI) = mte pointer
;
;       EXIT    CY Clear
;                 This means one of the following:
;                 - segment is the base of a huge resurce segment
;                 - segment is a single segment resource
;               CY Set
;                 segment is one of the subsegments of a huge resource
;
;       USES    ECX,EDX,FLAGS
;
;       PSEUDOCODE

ibrie1: Panic <'ldrIsBaseRsrc: resource not found'>
ibrie2: Panic <'ldrIsBaseRsrc: base segno gtr than passed in segno'>

        assume ds:FLAT, es:FLAT, fs:nothing, gs:nothing, ss:nothing
Procedure ldrIsBaseRsrc,near

        push    edi                     ; save pointer to mte
        push    esi                     ; save pointer to ste

        mov     edi,[edi].mte_swapmte   ; (EDI) - pointer to swappable mte
        mov     esi,[edi].smte_rsrctab  ; (DS:ESI) -> resource id table
        mov     edx,1

;       (DX) = current segment number

ibr4:   cmp     edx,[edi].smte_rsrccnt  ; any more resources?
        ja      short ibrie1            ;  no, internal error

        cmp     bx,[esi].ldrrsrc16_type ; do the type id's match?
        jne     short ibr8              ;  no, skip over to the next

        cmp     cx,[esi].ldrrsrc16_name ; do the name id's match?
        je      short ibr12

ibr8:   add     esi,(SIZE ldrrsrc16_t)  ; go to the next entry in resource tbl
        inc     edx
        jmp     short ibr4

;       (AX) = passed in segno
;       (DX) = base segno withing resource tbl with matching type id & name id

ibr12:  add     edx,[edi].smte_objcnt   ; compute the absolute ...
        sub     edx,[edi].smte_rsrccnt  ; ... segment number
        cmp     dx,ax                   ; are the two segno the same?
        ja      short ibrie2            ; internal error if base > segno

        pop     esi                     ; restore pointer to ste
        pop     edi                     ; restore pointer to mte

        RETC
EndProc ldrIsBaseRsrc


;***LP  RsrcFindLocal - Find a local reference to passed resource segment
;
;       Scans the local ptda resource segment list, returns far
;       pointer to matching block or carry if not found.
;
;       ENTRY:  (EBX) = Resource Type Id
;               (ECX) = Resource Name Id
;               (DX) = Owner
;               (ES:DI) = rsrc list
;
;       EXIT:   (ES:DI) = BMP record if exists
;               Carry set if not found
;
;       USES:   DI,ES,Flags

        ASSUME DS:FLAT, ES:NOTHING, FS:NOTHING, GS:NOTHING, SS:NOTHING

Procedure RsrcFindLocal,<near,far32>,local


rfl10:  or      di,di
        jz      short rfl30
        cmp     di, -1
        je      short rfl30

        cmp     es:[di].rsrc_typeid,ebx ; match on type id?
        jne     short rfl20

        cmp     es:[di].rsrc_nameid,ecx ; match on name id?
        jne     short rfl20

        cmp     es:[di].rsrc_mte,dx     ; match on owner?
        je      short rfl40

rfl20:  mov     di,es:[di].rsrc_localptr
        jmp     short rfl10

rfl30:  stc
        jmp     short rfl50

rfl40:  clc
rfl50:  RETC
EndProc RsrcFindLocal


;***EP  _LDRIsResource - test if an object is a resource object
;
;       ENTRY:  hob                     - object handle
;               hobmte                  - handle to mte
;               prsrc                   - pointer to resource list
;
;       EXIT:   NO_ERROR                - if object is a resource
;               ERROR_INVALID_FUNCTION  - object is not a resource
;
;       USES:   CX,EDX

Procedure _LDRIsResource
        ASSUME DS:FLAT, ES:FLAT, FS:NOTHING, GS:NOTHING, SS:NOTHING

        ArgVar          hob,DWORD
        ArgVar          hobmte,DWORD
        ArgVar          prsrc,DWORD
        LocalVar        pmte,DWORD
        LocalVar        pste,DWORD
        LocalVar        objnum,DWORD

        EnterProc

        SaveReg <ebx,esi,edi>

        SSToDS  eax,[objnum]
        PushP   eax                             ; return for index for object
        SSToDS  eax,[pste]
        PushP   eax                             ; return for ste pointer
        SSToDS  eax,[pmte]
        PushP   eax                             ; return for mte pointer
        PushP   hob                             ; hob
        PushP   hobmte                          ; mte hob
        CCALL32 _ldrFindObject,,,PushP
        or      eax,eax
        jnz     short lirsx

        mov     bx,word ptr objnum
        inc     bx                              ; make object number one based
        mov     edi,[pmte]
        mov     eax,[prsrc]
        CCALL32 ldrGetRsrcTypeName
        jc      short lir1

        mov     ax,word ptr [edi]     ; check for 32-bit module
        and     ax,MTEFORMATMASK
        cmp     ax,MTEFORMATLX
        je      short lira

        mov     ax,word ptr [objnum]
        inc     ax
        mov     esi,[pste]
        CCALL32 ldrIsBaseRsrc
        jc      short lir1

lira:   ;mov     eax,NO_ERROR                    ; object is a resource
        xor     eax,eax
        jmp     short lirsx

lir1:   mov     eax,ERROR_INVALID_FUNCTION      ; object is not a resource

lirsx:  RestoreReg      <edi,esi,ebx>
        LeaveProc
        RETC

EndProc _LDRIsResource



HIGH32CODE      ENDS

        FARCODE HIGH32

LOAD_FTUNE1_SWP segment

;***LP  IsHugeRsrc - Check if the passed segment is a huge resource segment
;
;       ENTRY   (AX) = segment number
;               (BX) = Resource Type Id
;               (CX) = Resource Name Id
;               (EDI) = mte pointer
;               (ESI) = ste pointer
;
;       EXIT    CARRY Clear [we have a huge resource]
;                 (CX) = huge segment count
;               CARRY Set [single segment resource]
;                 (CX) = 1
;
;       USES    EAX,EBX,ECX,EDX,FLAGS
;
;       PSEUDOCODE

        assume ds:FLAT, es:FLAT, fs:nothing, gs:nothing, ss:nothing
Procedure IsHugeRsrc,<near,far32>,local

        LocalVar        rid,WORD
        LocalVar        rtype,WORD

        EnterProc

        push    edi                     ;save pointer to mte
        push    esi                     ; save pointer to ste entry

        mov     edi,[edi].mte_swapmte   ; (EDI) - pointer to swappable mte
        mov     [rid],bx                ; [rid] = Resource Type Id
        mov     [rtype],cx              ; [rtype] = Resouce Type name

        mov     ebx,[edi].smte_objcnt   ; (EBX) = total number of segments
        sub     ebx,[edi].smte_rsrccnt  ; (EBX) = number of nonresrc segments
        xchg    eax,ebx                 ; (EAX) = num nonrsrc seg; (BX) = segno
        sub     ebx,eax                 ; (EBX) = seg number within resrc table
        mov     eax,[edi].smte_rsrccnt  ; (EAX) = number of resrc segments
        shl     eax,2                   ; (EAX) = size of resrc id table
        .ERRNZ  ((SIZE ldrrsrc16_t) - 4)
        shl     ebx,2                   ; 2 bytes each for NameId and TypeId
        mov     ecx,1                   ; initialise segment count
        mov     esi,[edi].smte_rsrctab  ; point to resource table

ihr4:   mov     dx,[rid]                ; check resource type id
        cmp     dx,[esi+ebx].ldrrsrc16_type; do the type id's match?
        jne     short ihr8              ;  no, return
        mov     dx,[rtype]              ; check resource name id
        cmp     dx,[esi+ebx].ldrrsrc16_name; do the name id's match
        jne     short ihr8              ;  no, return

        inc     ecx                     ; (ECX) = num of segments in this rsrc
        add     ebx,(SIZE ldrrsrc16_t)  ; advance to next resource's ids
        cmp     eax,ebx                 ; are we past the end of rsrc id table?
        ja      short ihr4

ihr8:   mov     eax,1
        cmp     eax,ecx                 ; do we have a huge resource
        cmc

        pop     esi                     ; (ESI) = pointer to ste entry
        pop     edi                     ; (EDI) = pointer to mte entry
        LeaveProc

        RETC
EndProc IsHugeRsrc


;***LP  _ldrProcessRsrcSeg - allocate a BMP record for a resource segment
;
;       ldrProcessRsrcSeg(pmte, hobptda, iste, fpreload)
;
;       ENTRY   pmte            - MTE pointer
;               hobptda         - PTDA handle
;               iste            - STE index
;               fused           - If true, set reference count to 1, else 0
;
;       EXIT    (EAX) = NO_ERROR
;                 A new BMP record is allocated and linked into
;                 local and global lists.
;               (EAX) = error code
;
;       USES    EAX, EBX, ECX, Flags
;
;       PSEUDOCODE
;
;       (cy,bx=type,cx=name) = ldrGetRsrcTypeName (eax=prsrc,bx=segno,ds=mtesel);
;       if (CY set)                             /* not a resource */
;         internal error
;       else                                    /* this is a resource */
;         (cy,ax=errcode,es:di->rmprec) = ldrRsrcAlloc(ebx=type,ecx=name,dx=mtehdl)
;       return

Procedure _ldrProcessRsrcSeg,near
        ASSUME DS:FLAT, ES:FLAT, FS:NOTHING, GS:NOTHING, SS:NOTHING

        ArgVar  prs_pmte,DWORD          ; MTE pointer
        ArgVar  prs_hobptda,DWORD       ; PTDA handle
        ArgVar  prs_iste,DWORD          ; STE index
        ArgVar  prs_fused,DWORD         ; True if resource actually used

        EnterProc
        SaveReg <ebx,esi,edi>

;       (cy,bx=typeid,cx=nameid) = ldrGetRsrcTypeName(eax=prsrc,bx=segno,edi=mteptr)

        xor     eax,eax                 ; (EAX) = prsrc only for 32-bit rsrcs
        mov     bx,prs_iste.LowWord     ; (BX) = ste index (1-based)
        mov     edi,[prs_pmte]          ; (EDI) = MTE pointer
        CCALL32 ldrGetRsrcTypeName      ; if a rsrc, gets Type and Name ID's
        jc      short prsie             ;  internal error if not a resource
        mov     dx,[edi].mte_handle     ; (DX) = MTE handle
        mov     di,prs_iste.LowWord     ; (DI) = segment number

;       (EBX) = Resource TypeID
;       (ECX) = Resource NameID
;       (DX) = mtehdl (owner)
;       (DI) = segment number
;
;       (cy) = ldrIsBaseRsrc (ax=segno,ebx=typeid,ecx=nameid,edi=mteptr,esi=steptr)

        push    dx                      ; (DX) = mte handle
        mov     ax,di                   ; (AX) = segment number
        mov     edi,[prs_pmte]          ; (EDI) = pointer to mte
        CCALL32 ldrIsBaseRsrc
        pop     dx                      ; (DX) = mte handle
        mov     eax,NO_ERROR            ; do not destory carry flag (assume failed)
        jc      short prsx              ;  jump if non-fatal error
        mov     ax,prs_hobptda.LowWord  ; (AX) = PTDA handle

;       (AX) = ptda_child
;       (EBX) = Resource TypeID
;       (ECX) = Resource NameID
;       (DX) = mtehdl (owner)
;
;       (cy, ax) = ldrRsrcAlloc(ax=ptdachild,ebx=typeid,ecx=nameid,dx=mtehdl)

        CALL16  ldrRsrcAlloc
        movzx   eax,ax                  ; (EAX) = error code
        jc      short prsx

; We need to check if this is the preload load of this resource.  If it is
; we need to increment the resource count so all preloaded resources have a
; initial resource count of one.

        mov     eax,prs_fused           ; (EAX) = resource used flag
        or      eax,eax                 ; Used?
        jz      short prsx              ;  no, exit

        mov     edi,prs_pmte

;       (EBX) = Resource TypeID
;       (ECX) = Resource NameID
;       (DX) = mtehdl (owner)
;       (EDI) = pointer to mte

        CALL16  ldrIncRefCount
;       sbb     edx,edx                 ; (EDX) = -1 if error, else 0
;       movzx   eax,ax                  ; (EAX) = error code or garbage
;       and     eax,edx                 ; (EAX) = error code or NO_ERROR

prsx:   RestoreReg <edi,esi,ebx>
        LeaveProc
        RETC

prsie:  Panic   "ldrProcessRsrcSeg: not a resource"

EndProc _ldrProcessRsrcSeg

LOAD_FTUNE1_SWP  ENDS
SWAP32_7   segment


;***LP  _ldrRsrcAlloc - C call interface for ldrRsrcAlloc
;
;       ENTRY   typeid                  - type id
;               nameid                  - name id
;               hobmte                  - handle of mte
;               pptda                   - pointer to ptda
;
;       EXIT    none                    - Resource record allocated
;

        ASSUME DS:FLAT, ES:FLAT, FS:NOTHING, GS:NOTHING, SS:NOTHING

Procedure _ldrRsrcAlloc,near

        ArgVar  typeid,DWORD
        ArgVar  nameid,DWORD
        ArgVar  hobmte,DWORD
        ArgVar  pptda,DWORD

        EnterProc

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

        mov     eax,[pptda]
        mov     ax,[eax].ptda_handle
        mov     ebx,[typeid]
        mov     ecx,[nameid]
        mov     dx,word ptr [hobmte]

        CALL16  ldrRsrcAlloc
        movzx   eax,ax          ; make sure upper word is clear (B721013 Edd)

lrax:   RestoreReg      <edi,esi,ebx,es,ds>
        LeaveProc
        RETC

EndProc _ldrRsrcAlloc
SWAP32_7 ENDS
SWAP32_5 segment


;***LP  _ldrIncRefCount - C call interface for IncRefCount
;
;       ENTRY   typeid                  - type id
;               nameid                  - name id
;               hobmte                  - handle of mte
;               pmte                    - pointer to mte
;
;       EXIT    none                    - Resource record incremented
;

        ASSUME DS:FLAT, ES:FLAT, FS:NOTHING, GS:NOTHING, SS:NOTHING

Procedure _ldrIncRefCount,near
        ArgVar  typeid,DWORD
        ArgVar  nameid,DWORD
        ArgVar  hobmte,DWORD
        ArgVar  pmte,DWORD

        EnterProc

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

        mov     ebx,[typeid]
        mov     ecx,[nameid]
        mov     dx,word ptr [hobmte]
        mov     edi,[pmte]

        CALL16  ldrIncRefCount

lircx:  RestoreReg      <edi,esi,ebx,es,ds>
        LeaveProc
        RETC

EndProc _ldrIncRefCount

SWAP32_5 ENDS
SWAP32_7 segment


;***LP  _ldrRsrcFindGlobal - C call interface for RsrcFindGlobal
;
;       ENTRY   objnum                  - object number
;               pmte                    - pointer to mte
;               psrc                    - pointer to resource list
;
;       EXIT    (EAX)                   - ERROR_BUSY objects is still in use
;                                         as a resource do not zero handle
;                                       - NO_ERROR resource no longer in use
;
;       USES
;

        ASSUME DS:FLAT, ES:FLAT, FS:NOTHING, GS:NOTHING, SS:NOTHING

lrfgsx: Panic<'_ldrRsrcFindGlobal: resource not found'>

Procedure _ldrRsrcFindGlobal,near

        ArgVar  objnum,DWORD
        ArgVar  pmte,DWORD
        ArgVar  prsrc,DWORD

        EnterProc

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

;       (cy,bx=typeid,cx=nameid) = ldrGetRsrcTypeName(eax=prsrc,bx=segno,edi=mteptr)

        mov     bx,word ptr [objnum]    ; (BX) segment number
        mov     edi,[pmte]              ; (EDI) pointer to mte
        mov     ax,word ptr [edi]     ; check for 32-bit module
        and     ax,MTEFORMATMASK
        cmp     ax,MTEFORMATLX
        mov     eax,[prsrc]             ; (EAX) pointer to resource list
        jne     short lrfg1a
        movzx   ecx,bx                  ; (ECX) name id
        mov     ebx,0ffffffffh          ; (EBX) typeid for 32-bit module
        jmp     short lrfg1

lrfg1a: CCALL32 ldrGetRsrcTypeName      ; if a rsrc, gets Type and Name ID's
        jc      short lrfgsx            ; interal error 16-bit rsrc not found

lrfg1:  mov     edx,[pmte]
        mov     dx,[edx].mte_handle     ; (DX) owner handle

        xor     ax,ax
        mov     es,ax                   ; (ES) = start search at head of list

        CCALL32 ldrRsrcFindGlobal
        mov     eax,ERROR_BUSY          ; assume object in use
        jnc     short lrfgsx1
        xor     eax,eax                 ; zero handle and sel in mte

lrfgsx1:
        RestoreReg      <edi,esi,ebx,es,ds>
        LeaveProc
        RETC

EndProc _ldrRsrcFindGlobal




;***LP  ldrRsrcFindGlobal - Find a global reference to passed resource segment
;
;       Scans the global resource segment list, returns far
;       pointer to matching block or carry if not found.
;
;       ENTRY:  (EBX) = Resource Type Id
;               (ECX) = Resource Name Id
;               (DX) = Owner
;               if search should start at the head of global list
;                 (ES) = 0
;               else
;                 (ES:DI) -> bmp record at which to start the search
;
;       EXIT:   (ES:DI) = BMP record if exists
;               Carry set if not found
;
;       USES:   DI, ES, Flags

Procedure ldrRsrcFindGlobal,,local
        ASSUME DS:FLAT, ES:FLAT, FS:NOTHING, GS:NOTHING, SS:NOTHING

        SaveReg <eax>
        mov     eax,es
        or      eax,eax                 ; is the selector NULL?
        RestoreReg <eax>
        jnz     short rfg20             ; no, we have (ES:DI) -> bmp record

        les     di,[RsrcHead]           ; address global list

rfg20:  or      di,di                   ; at end of list?
        jz      short rfg40             ; return error if so

        cmp     es:[di].rsrc_typeid,ebx ; match on type id?
        jne     short rfg30             ; no, next block

        cmp     es:[di].rsrc_nameid,ecx ; match on name id?
        jne     short rfg30             ; no, next block

        cmp     es:[di].rsrc_mte,dx     ; match on owner?
        je      short rfg50             ; yes, return success

rfg30:  mov     di,es:[di].rsrc_globalptr
        jmp     short rfg20

rfg40:  stc
rfg50:  RETC
EndProc ldrRsrcFindGlobal


SWAP32_7 ENDS
SWAP32_5 segment

;***LP  _ldrCheckForResource - check if objects is resource
;
;       ENTRY   objnum                  - object number
;               pmte                    - pointer to mte
;               prsrc                   - pointer to rsrc list
;               pptda                   - pointer to ptda
;               lflags                  - flag for task termination
;
;       EXIT    (EAX)                   - ERROR_BUSY objects is still in use
;                                         as a resource do not delete
;                                       - ERROR_INVALID_FUNCTION
;                                         objects is not a resource object
;                                       - NO_ERROR object is to be removed
;
;       USES
;

        ASSUME DS:FLAT, ES:FLAT, FS:NOTHING, GS:NOTHING, SS:NOTHING

Procedure _ldrCheckForResource,near

        ArgVar  objnum,DWORD
        ArgVar  pmte,DWORD
        ArgVar  prsrc,DWORD
        ArgVar  pptda,DWORD
        ArgVar  lflag,DWORD

        EnterProc

        SaveReg <es,ebx,esi,edi>

;       (cy,bx=typeid,cx=nameid)=ldrGetRsrcTypeName(eax=prsrc,bx=segno,edi=mteptr)

        mov     bx,word ptr [objnum]
        mov     edi,[pmte]
        mov     eax,[prsrc]
        CCALL32 ldrGetRsrcTypeName      ; if a rsrc, gets Type and Name ID's
        jc      short lcfrsx

        push    dx
        mov     dx,word ptr [edi]     ; check for 32-bit module
        and     dx,MTEFORMATMASK
        cmp     dx,MTEFORMATLX
        pop     dx
        je      short lcfra

;       (cy) = ldrIsBaseRsrc (ax=segno,ebx=typeid,ecx=nameid,edi=mteptr)

        mov     ax,word ptr [objnum]
        mov     esi,[pste]
        CCALL32 ldrIsBaseRsrc
        jc      short lcfrsx1

;       (cy,es:di->bmprec) = RsrcFindLocal(ebx=typeid,ecx=nameid,dx=hmte,es=ptda)

lcfra:  mov     edx,[pmte]
        mov     dx,[edx].mte_handle
        les     di,[prsrc]
        CCALL32 RsrcFindLocal
        jc      short lcfr2             ; check for global

        test    lflag,VMFM_TASK_TERM
        jnz     short lcfr1
        mov     ax,es:[di].rsrc_refcount
        or      ax,ax
        jz      short lcfrie1           ; error ref count zero
        dec     ax
        mov     es:[di].rsrc_refcount,ax
        or      ax,ax
        jnz     short lcfrsx1           ; still in use

;(cy,es:bx=bmp) = ldrRsrcDeleteLocal(ebx=typeid,ecx=nameid,dx=hmte,es:di=rsrclist)

lcfr1:  push    bx                      ; (BX) = type id
        les     di,[prsrc]
        mov     eax,[pptda]
        CCALL32 ldrRsrcDeleteLocal
        jc      short lcfrie2           ; error no record found

;       (cy) = ldrRsrcDeleteGlobal(es:bx=bmprecord)

        CCALL32 ldrRsrcDeleteGlobal
        jc      short lcfrie2

        pop     bx                      ; (BX) = type id

lcfr2:  xor     eax,eax                 ; delete resource
        jmp     short lcfr

lcfrsx:
        mov     eax,ERROR_INVALID_FUNCTION; not a resource segment
        jmp     short lcfr

lcfrsx1:
        mov     eax,ERROR_BUSY          ; do not delete object

lcfr:   RestoreReg      <edi,esi,ebx,es>
        LeaveProc
        RETC

lcfrie1:Panic <'ldrCheckForResource: ref count zero'>
lcfrie2:Panic <'ldrCheckForResource: no record found'>

EndProc _ldrCheckForResource
SWAP32_5  ENDS
SWAP32_7 segment



;***LP  ldrRsrcDeleteLocal - Delete a local reference to passed resource segment
;
;       ENTRY:  (EAX) = pptda
;               (EBX) = Resource Type Id
;               (ECX) = Resource Name Id
;               (DX) = Owner
;               (ES:DI) -> rsrc list
;
;       EXIT:   Carry Clr
;                 (ES:BX) = pointer to BMP record, the record unlink from the
;                           local list.
;               Carry set
;                 rsrc record not found
;
;       USES:   AX, BX, DI, SI, ES, Flags

Procedure ldrRsrcDeleteLocal,,local

        ASSUME DS:FLAT, ES:NOTHING, FS:NOTHING, GS:NOTHING, SS:NOTHING
        LocalVar        <rdl_offset>,WORD

        EnterProc

;       Delete from local chain

        xor     esi,esi

rdl10:  or      di,di
        stc
        jz      short rdlx

        cmp     es:[di].rsrc_typeid,ebx ; match on type id?
        jne     short rdl20

        cmp     es:[di].rsrc_nameid,ecx ; match on name id?
        jne     short rdl20

        cmp     es:[di].rsrc_mte,dx     ; match on owner?
        je      short rdl40

rdl20:  mov     si,di
        mov     di,es:[di].rsrc_localptr
        jmp     short rdl10

;       Found our guy.  First entry on list?

rdl40:  mov     [rdl_offset],di         ; save offset to the record
        mov     di,es:[di].rsrc_localptr
        or      si,si
        jnz     short rdl50             ; not first entry

        mov     [eax].ptda_rsrclist.Offst,di
        mov     [eax].ptda_rsrclist.Segmt,es
        jmp     short rdl80

rdl50:  mov     es:[si].rsrc_localptr,di; make prev point to next

rdl80:  mov     bx,[rdl_offset]         ; (BX) = offset to record in BMP seg
rdlx:   LeaveProc
        RETC
EndProc ldrRsrcDeleteLocal




;***LP  ldrRsrcDeleteGlobal - Delete a global reference to passed resource segment
;
;       ENTRY:  (BX) = offset to record to be unlinked from global list
;
;       EXIT:   Carry Clear
;                 record unlinked from global list
;               Carry set if record not found
;
;       USES:   AX, DI, SI, ES, Flags

Procedure ldrRsrcDeleteGlobal,,local
        ASSUME DS:FLAT, ES:NOTHING, FS:NOTHING, GS:NOTHING, SS:NOTHING

        les     di,[RsrcHead]           ; address global list
        xor     esi,esi

rdg10:  or      di,di
        stc
        jz      short rdgx

        cmp     di,bx                   ; is this the record to unlink?
        je      short rdg40

rdg20:  mov     si,di
        mov     di,es:[di].rsrc_globalptr
        jmp     short rdg10

;       Found the record.  First entry on list?

rdg40:  mov     ax,es:[di].rsrc_globalptr

;BUGBUG this is here for debugging

        mov     es:[di].rsrc_localptr,0ffffh;

        or      si,si
        jnz     short rdg50             ; not first entry

        mov     [RsrcHead].Offst,ax
        jmp     short rdg80

rdg50:  mov     es:[si].rsrc_globalptr,ax       ; make prev point to next

;       () = Bmp_Free(es:di->bmprec)

rdg80:  CALL16  Bmp_Free                ; Bmp_Free(es=bmp segment,di=offset)
        clc
rdgx:   RETC
EndProc ldrRsrcDeleteGlobal

SWAP32_7     ENDS
LOAD_FTUNE1_SWP segment



;***LP  ldrGetRsrcSel - C callable interface for GetRsrcSel
;
;       This routine is the C callable interface for GetRsrcSel
;
;       ENTRY   typeid                  - Resource typeid
;               nameid                  - Resource nameid
;               hob                     - handle to module
;               pmte                    - pointer to mte
;               segno                   - segment number
;               paddr                   - pointer to return address in

        ASSUME DS:FLAT, ES:FLAT, FS:NOTHING, GS:NOTHING, SS:NOTHING

Procedure _ldrGetRsrcSel,near
        ArgVar  typeid,DWORD
        ArgVar  nameid,DWORD
        ArgVar  hob,DWORD
        ArgVar  pmte,DWORD
        ArgVar  segno,DWORD
        ArgVar  paddr,DWORD

        EnterProc
        SaveReg <ebx,esi,edi>

        mov     eax,[segno]             ; (EAX) segment number
        mov     bx,word ptr [typeid]    ; (BX) typeid
        mov     cx,word ptr [nameid]    ; (CX) nameid
        mov     dx,word ptr [hob]       ; (DX) module handle
        mov     edi,[pmte]              ; (EDI) pointer to mte
        CALL16  GetRsrcSel
        jc      short lgrs1

        mov     ebx,[paddr]
        mov     word ptr [ebx+2],ax     ; return selector
        xor     eax,eax                 ; return NO_ERROR
        mov     word ptr [ebx],ax       ; return zero for offset

lgrs1:  RestoreReg <edi,esi,ebx>
        LeaveProc
        RETC

EndProc _ldrGetRsrcSel




;***LP  _ldrFreeHuge - Free all segments of a huge resource.
;
;       This routine is called to check if this resource is a huge resource.
;       If it is than we must delete all the segments of the huge resource.
;
;       ENTRY:  objnum                  - start object number of huge resource
;               pmte                    - pointer to mte
;
;       EXIT:   none
;
        ASSUME DS:FLAT, ES:FLAT, FS:NOTHING, GS:NOTHING, SS:NOTHING

lfhsx:  Panic<'_ldrFreeHuge: resource not found'>

Procedure _ldrFreeHuge

        ArgVar          objnum,DWORD
        ArgVar          pmte,DWORD

        EnterProc

        SaveReg <ebx,esi,edi>                   ; C callable

        xor     eax,eax                         ; no pointer to rsrc list needed
        mov     bx,word ptr [objnum]            ; (BX) segment number
        mov     edi,[pmte]                      ; (EDI) pointer to mte

        CCALL32 ldrGetRsrcTypeName              ; get type and name id's
        jc      short lfhsx                     ; must find type and name id

        push    ecx                             ; (ECX) nameid
        mov     eax,[objnum]                    ; (EAX) segment number
        dec     eax                             ; make segment zero based
        mov     edi,[edi].mte_swapmte           ; (EDI) - swappable mte pointer
        mov     esi,[edi].smte_objtab           ; get ste pointer
        mov     edi,[pmte]                      ; (EDI) - ptr to resident mte
        mov     ecx,SIZE ldrste_s               ; compute pointer into ste
        imul    eax,ecx
        add     esi,eax                         ; (ESI) pointer to ste
        mov     eax,[objnum]                    ; (EAX) segment number
                                                ; (EBX) typeid
        pop     ecx                             ; (ECX) nameid
                                                ; (EDI) pointer to mte
        CCALL32 IsHugeRsrc                      ; Is this a huge resource
        jc      short lfhret                    ; no segments to free

lfh1:   dec     cx
        push    ecx                             ; (ECX) count of huge segments
        add     esi,SIZE ldrste_s               ; (ESI) pointer to ste
        movzx   eax,[esi].ste_selector

ifdef   LDRSTRICT
        test    eax,SEL_LDTBIT
        jz      short lfhie1
endif
        xor     cx,cx
        mov     [esi].ste_seghdl,cx             ; mark entry as free
        mov     [esi].ste_selector,cx

        pop     ecx                             ; (ECX) count of huge segments
        cmp     ecx,1
        ja      short lfh1

lfhret: RestoreReg      <edi,esi,ebx>
        LeaveProc
        RETC

ifdef   LDRSTRICT
lfhie1: Panic   <'ldrFreeHuge not LDT selector'>
endif

EndProc _ldrFreeHuge

LOAD_FTUNE1_SWP ENDS

        END
