;       SCCSID = @(#)demfcb2.asm        6.5 92/03/04
;***EM  demfcb2.asm
;       Version 1.9, for src/dos/mvdm/demfcb2.asm, dem, mer.krnl, 960610.1
;       SUMMARY
;           DOS Emulation FCB Support
;
;       NOTES
;
;       REVISIONS
;
;Local  DCR/
;Tag    PTR     Who     When
;               danno   21-Mar-1989
;                   Created for MVDM
;@53195 53195   DougA   07-01-92  remove SFT sharing for FCBs
;1.6    56384   Madden  11-19-92  Added QFileInfo for FCB Open
;
;***********************************************************************;BN040;
;  29Jul93 - J.M.Hare    defect 71358                                   ;BN040;
; Add propogating of DOSFLAG through files system for exec_only test.   ;BN040;
;***********************************************************************;BN040;
;  11/27/95 MLM  72417 moved from PTDA to TCB:
;                      pSrchBuf, cMeta, Attrib
;  05/15/96 Gordon Kuo defect 152902
;         Reference lCurDRV through TKOPTDA pointer
;
;
;
;

;
;   Throughout the routines in this file, when loading registers
;   from the client stack frame, we will perform a 32-bit load.
;   Generally, the upper-16 bits of the register are ignored and
;   only the lower 16-bits are needed.  This is done only to avoid
;   an override.
;
;   When storing registers into the stack frame, however, we always
;   perform 16-bit stores, since the upper 16-bits of the 32-bit
;   registers are reserved *exclusively* for DOS applications.
;
;   -- danno 08-Mar-1989

INCL_DEF        equ     1                       ; include typedef macros
INCL_TYPES      equ     1

.xlist
include osconst.inc
include dosseg.inc
.xcref
include basemaca.inc
include basedef.inc
include osmaca.inc
include dossymc.inc
include kmode.inc
include mi.inc
include opncreat.inc
include curdir.inc
include dirent.inc
include sem.inc
include screen.inc
include dem.inc
include error.inc
include argframe.inc
include sft.inc
include cpmfcb.inc
include inbuf.inc
include tkexport.inc
                                      ;72417 moved find.inc after tkexport.inc
include find.inc
include filesys.inc
include pgexport.inc
include vmexport.inc
include filemode.inc
include syscalls.inc
include infoseg.inc
include sigdef.inc
include except.inc
include tkptda.inc
.cref
.list

        CpuMode 386

        EXTRN16         TransFCB
        EXTRN16         GetExtended
        EXTRN16         ChkIFSVol
        EXTRN16         LRUFCB
        EXTRN16         FSD_OpenCreate
        EXTRN16         BlastSFT
        EXTRN16         FCBHardErr
        EXTRN16         SaveFCBInfo
        EXTRN16         SetOpenAge
        EXTRN16         CheckFCB
        EXTRN16         MFTclose
        EXTRN16         SFTFromFCB
        EXTRN16         SFT_SetFileInfo
        EXTRN16         FSD_Close
        EXTRN16         w_Get_FCB_File_Length
        EXTRN16         FCBIO
        EXTRN16         Date16
        EXTRN16         w_FCB_VolId
        EXTRN16         SFT_QFileInfo                                   ;1.6

DefData IMPORT, GLOBAL, C
USHORT  sftFCB
EndData

DefData IMPORT, GLOBAL
USHORT  FCBLRU
EndData

DefCode IMPORT, SWAP
DefFn   demMapDSDX
EndData

        FARCODE HIGH32
DefCode PRIVATE, SWAP, PASCAL

;***LP  demFCBOpen - Open the specified FCB
;
;       Open the specified FCB
;
;       ENTRY
;           AX
;               Open flags
;           VSF(DS:DX)
;               FCB to open
;           VSF(BX)
;               Attributes (for create)
;
;       EXIT
;           SUCCESS
;               CF = 0
;               AL = 0
;
;           ERROR
;               CF = 1
;               AX = error code
;
;           HARD ERROR
;               CY = 1
;               AX = 0FFFFh
;
;       CONTEXT
;           Called from V86 mode at task time
;
;       STEPS
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;
;       USES
;           EAX,EBX,ECX,EDX,ESI,EDI,DS,ES
;
;
        ASSUME  DS:FLAT,ES:FLAT,SS:TASKAREA,FS:NOTHING,GS:NOTHING
        align   4

Procedure demFCBOpen,near

LocalVar  fcbo_ulOpenFlags,DWORD
LocalVar  fcbo_ulAttributes,DWORD
LocalVar  fcbo_ArgFrame,<size Open3Struc> ; frame to pass to FSD_OpenCreate
                                          ; BN022
LocalVar  fcbo_searchbuf,SRCHBUFSIZE+1
LocalVar  fcbo_openbuf,PMPATHLEN
LocalVar  fcbo_dummy,WORD                 ; KLUDGE: see gshare.asm
LocalVar  fcbo_dummycds,<SIZE curdir>
LocalVar  fcbo_dttime,<SIZE inbuf>        ; for QFileInfo                1.6

        EnterProc <eax, [ebx].vsf_ebx>

        lea     cx,fcbo_dummycds
        SaveReg <ebx>                    ;### PTR B720732
        mov     ebx,[_pTCBCur]           ;### PTR B720732

;### PTR B720732        mov     ss:[TKOPTDA].ptda_pCDS,ax; Initialize ptda_pCDS
        mov     [ebx].TCBpTmpCDS.Offst,cx      ; Initialize ptda_pCDS ;### PTR B720732
        lea     cx,fcbo_searchbuf

                                              ;72417 moved from PTDA to TCB
        mov     [ebx].TCB_pSrchBuf,cx ; Initialize ptda_pSrchBuf
                                              ;72417 end
        lea     cx,fcbo_openbuf

;###    mov     SS:[TKOPTDA.ptda_pOpenBuf],cx ; Initialize ptda_pOpenBuf
        mov     [ebx].TCBpOpenBuf,cx          ; Initialize ptda_pOpenBuf

        RestoreReg <ebx>                      ; ### PTR B720732

        call    demMapDSDX
    ASSUME   DS:NOTHING

        CALL16  ChkIFSVol               ; JR PTR B712145: IFS checking was
                                        ; missing.
        jc      dof10                   ; any error? go report it
        jz      short dof0              ; no, Is it label open on IFS?

        mov     ax,2                    ; indicate that this is a create call.

;;;;;;  TODO - visibility to an equate instead of 2?

        CALL16  w_FCB_VolId             ; Create the label.
        jmp     dof10                   ; Go tell caller about it (or error).

; Handle normal case (not label on IFS vol).
dof0:   lea     di,fcbo_openbuf
        SaveReg <edx, ds>
        CALL16  TransFCB                ; get an ASCIIZ name
        RestoreReg <ds, edx>
    ASSUME   DS:NOTHING,ES:NOTHING
        jc      dof2                    ; exit if failed
                                        ;72417 moved from PTDA to TCB
        push    bp
        mov     bp,ss:[TKOPTDA].CurrTCB
        cmp     ss:[bp].TCBcMeta,-1     ; meta-characters?
        pop     bp
                                        ;72417 end
        jne     dof2                    ; abort if so
        CALL16  GetExtended
        movzx   esi,si
        SaveReg <ebp>
        CALL16  LRUFCB                  ; get an SFT
        RestoreReg <ebp>
;
; BlastSFT, called by LRUFCB, sets up the following fields:
; sf_flags = SF_FCB
; sf_ref_count = 0
; sf_mft = SF_MFT_NULL
;
        movzx   edi,di
        jc      dof1                    ; hard error if can't
    ASSUME   ES:NOTHING
;
; We need to set up a parameter frame on the stack to match the structure
; OpenStruc in ARGFRAME.INC. This is expected by FSD_OpenCreate.
; The opns_NamePtr field is not used in FSD_OpenCreate or DOS_OpenCreate,
; so we do not need to set it.
;
; fcbo_ulOpenFlags = flags for open/create operation (OPEN/CREATE/REPLACE/FAIL)
; fcbo_ulAttributes = attributes (for create)
;
        xor     eax,eax
                                                ; BN022
        mov     [fcbo_ArgFrame].opn3s_FileHandleLockIDPtr,eax ; assume no LockID ptr
        mov     [fcbo_ArgFrame].opn3s_EABufPtr,eax
        mov     [fcbo_ArgFrame].opn3s_Size,eax
        mov     [fcbo_ArgFrame].opn3s_Mode2,ax

        mov     eax,[fcbo_ulOpenFlags]
        mov     [fcbo_ArgFrame].opn3s_Flag,ax
        mov     eax,[fcbo_ulAttributes]
        mov     [fcbo_ArgFrame].opn3s_Attrs,ax

        mov     ax,open_for_both + sharing_compat
        mov     [fcbo_ArgFrame].opn3s_Mode,ax
                                                ; BN022
        mov     es:[edi].sf_fsi.sfi_mode,ax
;
; Set up PDB, PID, and UID in SFT.
;
        mov     ax,ss:[TKOPTDA.CurrentPDB]
        mov     es:[edi].sf_fsi.sfi_PDB,ax
        push    ebp
        movzx   ebp,ss:[TKOPTDA.CurrTCB]
        mov     ax,[ebp].TCBProc_ID
        mov     es:[edi].sf_fsi.sfi_PID,ax
        mov     ax,[ebp].TCBUser_ID
        mov     es:[edi].sf_fsi.sfi_UID,ax
        pop     ebp

        SaveReg <ds, esi>               ; save FCB pointer
        TaskContext ds
        lea     ebx,[fcbo_ArgFrame]     ; SS:BX -> Argument frame

        xor     ch,ch                   ; exec_only BN040
        and     ch, not EXECOPEN        ; set exec_only bit off exec_only BN040

        CALL16  FSD_OpenCreate          ; Go OPEN/CREATE the file
        RestoreReg  <esi, ds>           ; DS:ESI -> FCB
    ASSUME   DS:NOTHING
        movzx   edi,ss:[TKOPTDA.CurrTCB]
        les     di,ss:[edi].TCBThisSFT  ; get SF pointer
        jnc     short dof3              ; operation succeeded

        push    eax
        mov     al,"R"                  ; clear out field (free SFT)
        CALL16  BlastSFT
        pop     eax
        cmp     ax,ERROR_TOO_MANY_OPEN_FILES
        jz      short dof1
        cmp     ax,ERROR_SHARING_BUFFER_EXCEEDED
        jnz     short dof2
dof1:   push    eax
        CALL16  FCBHardErr
        pop     eax
dof2:   stc
        jmp     dof10

dof3:   SaveReg <ecx>                   ; save FSD_OpenCreate's action
        inc     es:[edi].sf_ref_count   ; increment reference count
        CALL16  SaveFCBInfo
        CALL16  SetOpenAge
        test    es:[edi].sf_flags,DEVID_DEVICE
        jnz     short dof4              ; do not munge drive on devices
        mov     al,ds:[esi]             ; get drive byte
        or      al,al                   ; default drive?
        jnz     short dof4              ; no, it's okay
                        ;72417 changed reference from ss:[TKOPTDA.LCurDrv]
	                ;152902 changed reference back from ss:[LCurDrv]
        mov     al,ss:[TKOPTDA.LCurDrv] ; convert drive letter
        inc     al
        mov     ds:[esi],al             ; stash in good drive letter
dof4:   mov     [esi].fcb_RECSIZ,80h    ; stuff in default record size

; If FSD_OpenCreate opens an existing file, then we copy sfi_mtime/date into
; FCB_FTime/Date. If FSD_OpenCreate created a new file, then we call Date16
; and put current time/date into FCB_FTime/Date. This is because when a new
; file is created, the mtime/date fields are not necessarily set.

        RestoreReg <ecx>                ; cx = FSD_OpenCreate's action
        cmp     cx,file_exist           ; are mdate/mtime valid?
        je      short dof5              ;   yes, go store them in FCB
        CALL16  Date16                  ;   no, get current time/date
        jmp     short dof7
dof5:
        cmp     es:[edi].sf_fsi.sfi_mtime,0     ; modify time != 0?     ;1.6 begin
        jnz     short dof6                      ; yes, use it
        SaveReg <esi,edi,es,ds>
        TaskContext <ds>,esi
        lea     esi,fcbo_dttime         ; ds:esi -> fcbo_dttime struc
        mov     ecx,size inbuf          ; cx = size of input data buffer
        mov     edx,QINFOLEV_DATE_TIME  ; get date and time info (level 1)
        CALL16  SFT_QFileInfo           ; ds:esi ->fileinfobuf; es:edi->sft
                                        ; back door entry to w_QFileInfo
        lea     esi,fcbo_dttime         ; (ESI) = file info buffer
        mov     ax,ss:[esi].inbuf_lwdate        ; get last write date
        mov     dx,ss:[esi].inbuf_lwtime        ; get last write time
        RestoreReg <ds,es,edi,esi>
        jc      short dof6              ; if error, just return 0
        jmp     short dof7
dof6:                                                                   ;1.6 end
        mov     ax,es:[edi].sf_fsi.sfi_mdate    ; ax = last write date
        mov     dx,es:[edi].sf_fsi.sfi_mtime    ; dx = last write time
dof7:                                                                   ;1.6
    ASSUME   DS:NOTHING
        mov     [esi].fcb_FTIME,dx
        mov     [esi].fcb_FDATE,ax
        mov     eax,es:[edi].sf_fsi.sfi_size ; set sizes
        mov     dword ptr [esi].fcb_FILSIZ,eax
        xor     eax,eax                 ; convenient zero
        mov     [esi].fcb_EXTENT,ax     ; point to beginning of file
;
; @53195 The following code that shares SFTs causes several problems
;        with LAN and local SFT cleanup (see defects 53165, 53195).
;        Removing SFT sharing fixes the problem, but if ANY problems
;        pop up as a result, bring this code back and make the LAN
;        developers (and the VDM cleanup) support SFT reference counts
;;
;; We must scan the set of FCB SFTs for one that appears to match the current
;; one.  We cheat and use CheckFCB to match the FCBs.
;;
;        FlatContext <es>,edi
;        mov     es,[sftFCB]             ; get the pointer to head of the list
;    ASSUME   ES:NOTHING
;        mov     edi,size sft
;        mov     ah,byte ptr es:[sft_count]  ; get number of SFTs to scan
;dof6:   cmp     al,[esi].fcb_sfn        ; don't compare ourselves
;        jz      short dof7
;        SaveReg <eax>                   ; preserve count
;        CALL16  CheckFCB                ; do they match
;        RestoreReg <eax>                ; get count back
;        jnc     short dof8              ; found a match!
;dof7:   inc     al                      ; advance to next FCB
;        cmp     al,ah                   ; table full?
;        jnz     short dof6              ; no, go for more
;        jmp     short dof9              ; return success
;;
;; The SFT at ES:DI is the one that is already in use for this FCB.  We set the
;; FCB to use this one.  We increment its ref count.  We do NOT close it at all.
;; Consider:
;;
;;   open (foo)  delete (foo) open (bar)
;;
;; This causes us to recycle (potentially) bar through the same local SFT as
;; foo even though foo is no longer needed; this is due to the server closing
;; foo for us when we delete it.   Unfortunately, we cannot see this closure.
;; If we were to CLOSE bar, the server would then close the only reference to
;; bar and subsequent I/O would be lost to the redirector.
;;
;; This gets solved by NOT closing the sft, but zeroing the ref count
;; (effectively freeing the SFT) and informing the sharer (if relevant) that
;; the SFT is no longer in use.  Note that the SHARER MUST keep its ref counts
;; around.  This will allow us to access the same file through multiple network
;; connections and NOT prematurely terminate when the ref count on one
;; connection goes to zero.
;;
;dof8:   SaveReg <esi,ds>                ; preserve address of FCB
;        mov     [esi].fcb_sfn,al        ; assign with this
;        inc     es:[edi].sf_ref_count   ; remember this new invocation
;        FlatContext <ds>
;        mov     ax,FCBLRU               ; update LRU counts
;        mov     es:[edi].sf_LRU,ax
;
;; We have an FCB sft that is now of no use.  We release sharing info and then
;; blast it to prevent other reuse.
;
;        TaskContext <ds>
;        movzx   edi,ds:[TKOPTDA.CurrTCB]
;        les     di,ds:[edi].TCBThisSFT
;        dec     es:[edi].sf_ref_count   ; free the newly allocated SFT
;        CALL16  MFTclose
;        MOV     AL,'C'
;        CALL16  BlastSFT
;        RestoreReg <ds,esi>              ; (ds:esi) = FCB
;
; @53195 End

dof9:   xor     ax,ax                    ; indicate success
                                         ;72417 moved from PTDA to TCB
dof10:  push    bp
        mov     bp,ss:[TKOPTDA].CurrTCB
        mov     ss:[bp].TCB_pSrchBuf,0
        pop     bp
                                         ;72417 end
        LeaveProc
        ret
EndProc   demFCBOpen

;***LP  demFCBClose - Close the specified FCB
;
;       Close the specified FCB
;
;       ENTRY
;           VSF(DS:DX)
;               FCB to Close
;
;       EXIT
;           SUCCESS
;               CY = 0
;               AL = 0
;
;           ERROR
;               CY = 1
;               AX = error code
;
;           HARD ERROR
;               CY = 1
;               AX = 0FFFFh
;
;       CONTEXT
;           Called from V86 mode at task time
;
;       STEPS
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;
;       USES
;           EAX,EBX,ECX,EDX,ESI,EDI,DS,ES
;
;
        ASSUME  DS:FLAT,ES:FLAT,SS:TASKAREA,FS:NOTHING,GS:NOTHING
        align   4

Procedure demFCBClose,near

LocalVar  fcbc_dttime,SETINFOBUFSIZE    ; arg.frame to be passed to
                                        ; setfsinfo
LocalVar  fcbc_dummycds,<SIZE curdir>
LocalVar  fcbc_searchbuf,SRCHBUFSIZE+1
LocalVar  fcbc_openbuf,PMPATHLEN
LocalVar  fcbc_dummy,WORD               ; KLUDGE: see gshare.asm
        EnterProc
        lea     cx,fcbc_dummycds
        SaveReg <ebx>                    ;### PTR B720732
        mov     ebx,[_pTCBCur]           ;### PTR B720732

;### PTR B720732        mov     ss:[TKOPTDA].ptda_pCDS,ax; Initialize ptda_pCDS
        mov     [ebx].TCBpTmpCDS.Offst,cx      ; Initialize ptda_pCDS ;### PTR B720732
        lea     cx,fcbc_searchbuf

                                              ;72417 moved from PTDA to TCB
        mov     [ebx].TCB_pSrchBuf,cx         ; Initialize ptda_pSrchBuf
                                              ;72417 end
        lea     cx,fcbc_openbuf

;###    mov     SS:[TKOPTDA.ptda_pOpenBuf],cx ; Initialize ptda_pOpenBuf
        mov     [ebx].TCBpOpenBuf,cx          ; Initialize ptda_pOpenBuf

        RestoreReg <ebx>                      ; ### PTR B720732

        mov     ss:[TKOPTDA.SysCall],FCB_CLOSE  ; tell FCBRegen that it is a close
        call    demMapDSDX
    ASSUME   DS:NOTHING

        CALL16  ChkIFSVol               ; SB PTRB785908: IFS checking was
                                        ; missing.
        jc      dcf5                    ; any error? go report it
        jz      short dcf0              ; no, Is it label close on IFS
        xor     ax,ax                   ; Yes; Go fake that it worked
        jmp     dcf5

dcf0:   xor     al,al                   ; default search attributes
        CALL16  GetExtended             ; DS:SI point to real FCB
        movzx   esi,si
        jz      short dcf1              ; not extended
        mov     al,[esi-1]              ; get attributes
                                        ;72417 moved from PTDA to TCB
dcf1:   push    bp
        mov     bp,ss:[TKOPTDA].CurrTCB
        mov     SS:BYTE PTR [bp].TCBAttrib,al ; stash away found attributes
        pop     bp
                                        ;72417 end
        CALL16  SFTFromFCB
        movzx   edi,di
        jc      dcf4                    ; MZ 16 Jan Assume death

; if the file we're closing is on a file system that supports last write
; time stamp, then we copy time stamp from FCB into SFT and tell
; SetSFTTimes not to time stamp the last write time, just propagate it.
; The reason for copying time stamp from FCB is to allow old apps to change
; last write time to arbitrary value by changing the value in the FCB.
; This is how DOS3 works.
; es:edi -> sft
; ds:esi -> fcb

        test    es:[edi].sf_fsi.sfi_tstamp,ST_PWRITE ; wrt time stamp supported?
        jz      short dcf2              ; no, never mind the time stamps

        mov     bx,[esi].fcb_FDATE      ; move in the time and date
        mov     dx,[esi].fcb_FTIME
        SaveReg <esi,edi,ds,es>
        TaskContext <ds>,esi
        lea     esi,fcbc_dttime         ; ds:esi -> fcbc_dttime struc
        xor     eax,eax
        mov     [esi].inbuf_latime,ax   ; 0 in these fields => don't change
        mov     [esi].inbuf_ladate,ax   ; these values for the file
        mov     [esi].inbuf_ctime,ax    ;
        mov     [esi].inbuf_cdate,ax    ;
        mov     [esi].inbuf_lwdate,bx   ; set the last write time and date
        mov     [esi].inbuf_lwtime,dx   ;  properly
        mov     ecx,SETDATEBUFSIZE      ; cx = size of input data buffer
        mov     edx,SINFOLEV_DATE_TIME  ; level 1 to set
        CALL16  SFT_SetFileInfo         ; ds:esi ->fileinfobuf; es:edi->sft
                                        ; back door entry to w_SetFileInfo
        RestoreReg <es,ds,edi,esi>
    ASSUME   DS:NOTHING

dcf2:   mov     eax,dword ptr [esi].fcb_FILSIZ
        mov     es:[edi].sf_fsi.sfi_size,eax
        TaskContext <ds>                ; let Close see variables
        CALL16  FSD_Close
    assume ds:nothing

;       We don't call SFLinkFree here, because we're dealing with an FCB

        movzx   edi,ss:[TKOPTDA.CurrTCB]
        les     di,ss:[edi].TCBThisSFT
        pushfd
        cmp     es:[edi.sf_ref_count],0 ; zero ref count gets blasted
        jne     short dcf3
        push    eax
        mov     al,'M'
        CALL16  BlastSFT
        pop     eax
dcf3:   popfd
        jnc     short dcf4
        cmp     ax,ERROR_INVALID_HANDLE
        jz      short dcf4
        mov     ax,ERROR_FILE_NOT_FOUND
        jmp     short dcf5

dcf4:   xor     eax,eax
dcf5:   mov     ss:[TKOPTDA.SysCall],0  ; not a FCB_CLOSE any more

                                        ;72417 moved from PTDA to TCB
        push    bp
        mov     bp,ss:[TKOPTDA].CurrTCB
        mov     ss:[bp].TCB_pSrchBuf,0
        pop     bp
                                        ;72417 end
        LeaveProc
        or      ax,ax
        jnz     short dcf6
        ret

dcf6:   stc
        ret
EndProc   demFCBClose

;***LP  demFCBLength - Get the length of an FCB file
;
;       Get the length of an FCB file
;
;       ENTRY
;           VSF(DS:DX)
;               FCB to query
;
;       EXIT
;           SUCCESS
;               CY = 0
;               AL = 0
;
;           ERROR
;               CY = 1
;               AX = error code
;
;           HARD ERROR
;               CY = 1
;               AX = 0FFFFh
;
;       CONTEXT
;           Called from V86 mode at task time
;
;       STEPS
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;
;       USES
;           EAX,EBX,ECX,EDX,ESI,EDI,DS,ES
;
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING
        align   4

Procedure demFCBLength,near
        call    demMapDSDX
    ASSUME   DS:NOTHING
        CALL16  w_Get_FCB_File_Length
        ret
EndProc   demFCBLength

;***LP  demFCBIO - Perform FCB I/O
;
;       Perform FCB I/O
;
;       ENTRY
;           AL
;               Operation flags
;           VSF(DS:DX)
;               FCB with which to perform I/O
;           VSF(CX)
;               Number of records to transfer
;
;       EXIT
;           SUCCESS
;               CY = 0
;               AX = 0
;               VSF(CX) = number of records transferred
;               VSF(DL) = FCBErr
;
;           ERROR
;               CY = 1
;               AX = error code
;               VSF(DL) = FCBErr
;
;           HARD ERROR
;               CY = 1
;               AX = 0FFFFh
;
;       CONTEXT
;           Called from V86 mode at task time
;
;       STEPS
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;
;       USES
;           EAX,ECX,EDX,ESI,EDI,ES
;
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING
        align   4

Procedure demFCBIO,near
        mov     ecx,[ebx].vsf_ecx
        call    demMapDSDX
    ASSUME   DS:NOTHING
        CALL16  FCBIO
        ret
EndProc   demFCBIO

EndCode

        END
