SCCSID  equ     "@(#)opncreat.asm       6.9 92/05/21"
TITLE   OPNCREAT - open and create file system routines
NAME    OPNCREAT

;       IBM/Microsoft Confidential
;
;       Copyright (c) IBM Corporation 1987, 1989
;       Copyright (c) Microsoft Corporation 1987, 1989
;
;       All Rights Reserved
;
;   The FSD_ routine for opens and creates are in this file.
;   There are some procedure to fill in an SFT from a dir entry for FAT.
;   FSD_ routines are called from w_ and fcb_ routines.  They receive
;   an SFT which contains the open mode and flags.  FSD_ routines enter
;   the SFT into the sharing set and route the request to the proper
;   file system - dos or IFS.
;
;   2/6/92 Steve Best b712094 decreasing perfview overhead on the system
;                             check to see if it is up
;  4/15/92 Steve Best aa04936 move pvwcreateinstance_fil to only be called
;                             on good return code from opens
;  6/1/92  Steve Best aa05408 added paramters to pvwcreateinstance_fil
;  7/29/92 Steve Best 46691   only call pvwcreateinstance_fil if the dosopen
;                             is for a file
;  12/15/93 RAC  76699  Make Perfview optional with assmbly flag PERFVIEW
;
;  11/27/95 MLM  72417 moved from PTDA to TCB: Curr_Dir_End, DevPt,
;                      NoSetDir, PathNameType, WFP_Path_End, WFP_Start
;                      removed the following unused:
;                      ExtErr_Class, ExtErr_Action, ExtErr_Locus
;
;  02/05/96 Chg Team  148006  Called function was moved to a different segment.
;                             It needs to be a callfar.
;
;***********************************************************************;BN040;
;  29Jul93 - J.M.Hare    defect 71358                                   ;BN040;
; Add propogating of DOSFLAG through files system for exec_only test.   ;BN040;
;***********************************************************************;BN040;
;
;   Routines in this module:
;
;       Global          Local
;
;       FSD_OpenCreate
;       SHARE_ERROR
;       FillSFTFromDirEnt
;       FillDeviceSFT
;       GetBufBack

.xlist
include fnofs.inc
include dosseg.inc
include basemaca.inc
include osmaca.inc
include oldmaca.inc

.xcref
include dossymc.inc
include argframe.inc
include buffer.inc
include chardd.inc
include curdir.inc
include dirent.inc
include dpb.inc
include devhdr.inc
include error.inc
include extattr.inc
include fatea.inc
include filemode.inc
include filesys.inc
include fsc.inc
include tkexport.inc
                                      ;72417 moved find.inc after tkexport.inc
include find.inc
include mft.inc
include mi.inc
include mult.inc
include oplock.inc
include opncreat.inc
include sft.inc
include selxport.inc
include protmode.inc
include vpb.inc
include proc.inc
include shutdown.inc
.cref
.list
        ModName , FNO_OPNCREAT_ASM

        ReferGDT        GDT_FSC,WORD
        ReferGDT        GDT_VPB,WORD

        ReferGlobal     CharDevSem,DWORD

                                                ;72417 removed PTDA entries now
                                                ;      in TCB

        ReferTask       CurrTCB,WORD            ; Current thread control block
        ReferTask       ProcType,BYTE

        EXTRN           DecVPBRef:NEAR
        EXTRNFAR        Dev_Open_SFT
        EXTRNFAR        GetDevEntry
        EXTRN           FSD_Close:NEAR
        EXTRN           fValidFATDisk:NEAR
        EXTRN           IncVPBRef:NEAR
        EXTRN           MFTclose:NEAR
        EXTRN           Release:NEAR
        EXTRN           SET_BUF_AS_DIR:NEAR
        EXTRN           Share_Violation:NEAR
        EXTRN           ShSU:NEAR

ifdef FSSTRICT
        EXTRN           IsSFT:NEAR
endif


        EXTRNFAR        Date16
        EXTRNFAR        DOS_OpenCreate
        EXTRNFAR        GetBuffr
ifdef SECURITY
        EXTRNFAR        SecOpenPost                                       ;@SEC
        EXTRNFAR        SecOpenPre                                        ;@SEC
endif

        EXTRN32         _KSEMRequestMutex
        EXTRN32         _KSEMReleaseMutex
;       EXTRN32         KSEMRequestMutex
;       EXTRN32         KSEMReleaseMutex
        EXTRNF32        MFT_Enter

ifdef PERFVIEW
        EXTRN32         _PVWCreateInstance_Fil
endif

        ReferFlat       _pTCBCur,DWORD
        ReferFlat       _pPTDACur,dword

ifdef PERFVIEW
        ReferFlat       _fPerfview,DWORD                               ;b712094
endif
ifdef SECURITY
        ReferFlat       _fSec,BYTE                                     ;@SEC
endif

        FARCODE HIGH2
HIGH2CODE  SEGMENT
        ASSUME  SS:TASKAREA


;***    FSD_OpenCreate - Try to open, create or replace the specified file
;
;       FSD_OpenCreate is called to open, create or replace the file
;       specified in ThisSFT.
;       It enters the file in the sharing set, then routes it to the
;       appropriate file system, DOS or an FSD, to do the low level
;       work (filling in the rest of the sft in the DOS case).
;
;       ENTRY
;           Direct Access Open (only)
;               SS:BX -> Parameter frame on stack (See OpenStruc in argframe.inc)
;                       (only mode is important)
;               [TCBThisSFT] Points to SFT to fill in if file found
;                       sf_fsi.sfi_mode field set
;                       sf_flags = 0 or SF_FCB
;                       sf_MFT = SF_MFT_NULL
;               [TCBThisFSC] set up with the FSC pointer for the path specified.
;               [TCBThishVPB] set up with the hVPB
;               [PathNameType] specifies path type - net, file, char device,
;                       or pseudo char device
;
;           non-Direct Access Open
;               SS:BX -> Parameter frame on stack (See OpenStruc in argframe.inc)
;               [WFP_START] Points to WFP string ("d:\" must be first 3
;                       chars, NUL terminated)
;               [CURR_DIR_END] Points to end of Current dir part of string
;                       ( = -1 if current dir not involved, else Points
;                        to first char after last "\" of current dir part)
;               [ThisCDS] Points to CDS being used
;                       (Low word = -1 if NUL CDS (Net direct request))
;               [TCBThisSFT] Points to SFT to fill in if file found
;                       sf_fsi.sfi_mode field set
;                       sf_flags = 0 or SF_FCB
;                       sf_MFT = SF_MFT_NULL
;               [TCBThisFSC] set up with the FSC pointer for the path specified.
;               [TCBThishVPB] set up with the hVPB
;               [Sattrib] Is attribute of search, determines what files can
;                       be found
;               [PathNameType] specifies path type - net, file, char device,
;                       or pseudo char device
;               [DevPt] points to device header if path is char device
;               If (fSharing and open)   /* server */
;                  TCBCookie contains server per-file cookie
;                  TCBOpFlags contains flag indicating whether server wants an oplock/opbatch
;                     opnolockrequested == 0
;                     oplockrequested == 1
;                     opbatchrequested == 2
;
;       EXIT    sf_ref_count is NOT altered
;               'NC' if success
;                   TCBThisSFT filled in.
;                   CX = Action taken (FILE_EXIST, FILE_CREATE, FILE_REPLACE)
;               'C' if error
;                   AX is error code
;                       error_file_not_found
;                               Last element of path not found
;                       error_path_not_found
;                               Bad path (not in curr dir part if present)
;                       error_invalid_access
;                               Bad sharing mode and/or bad access mode
;                       ERROR_ACCESS_DENIED
;                               Attempt to open read only file for writting, or
;                               open a directory
;                       error_sharing_violation
;                               The sharing mode was correct but not allowed
;                               generates an INT 24 on compatibility mode SFTs
;                       error_sharing_buffer_exceeded
;                               Couldn't grow the sharing table.
;
;       USES    AX, BX, CX, DX, DI, SI, ES, Flags
;
;       ALGORITHM
;
;           Set up sf_devptr from [DevPt] for devices
;           MFT_Enter()
;           if (error) {
;               Share_Error()
;               return
;           }
;           if (!device)
;               IncVPBRef()
;           if FSD
;               FS_OpenCreate()
;               if (!error)
;                   update sf_flags from sfi_type
;                   if (CREATEd or REPLACEd)
;                       Func = 5
;                   else
;                       Func = 4
;           else
;               DOS_OpenCreate()
;               if (!error)
;                   if (CREATEd or REPLACEd)
;                       Func = 2
;                   else
;                       Func = 3
;           if (error)
;               if (!device)
;                   DecVPBRef()
;               MFTclose()
;           else
;               ShSU(Func)
;           Return any error indication
;
Procedure   FSD_OpenCreate,<hybrid, far16>
        SegAssert SS, <DS>
    ASSUME  DS:TASKAREA, ES:NOTHING, SS:TASKAREA
        PMONLY

USE_TCB     equ -1                    ;AA05408 USE_TCB to signal good TCB data

LocalVar    fsoc_OpenFlag,WORD          ; OpenFlag from caller
LocalVar    fsoc_Args,WORD              ; Word ptr to stack frame         ;@SEC
LocalVar    fsoc_ActionTaken,WORD       ; Location to place action taken
LocalVar    fsoc_devfsd,DWORD           ; DWORD passed in for attach of remote device
LocalVar    fsoc_fgenflag,WORD          ; == 1 if there are need eas otherwise 0
LocalVar    fsoc_execonly,WORD          ; exec_only flag BN040
LocalVar    fsoc_fSec,WORD              ; Keep local copy on stack for performance @SEC

        mov     di,TASKAREA:[bx].opn3s_Flag ; DI = openflag (actions to be taken)
        EnterProc <di,bx>                  ; Set up fsoc_OpenFlag for later use  @SEC

        mov     [fsoc_execonly],0             ; Must put here for later addressabilty  exec_only BN040
        mov     byte ptr [fsoc_execonly],ch   ; Must put here for later addressabilty  exec_only BN040

        mov     [fsoc_fgenflag],0       ; assume no need EAs
        mov     di,CurrTCB
        les     di,[di].TCBThisSFT ; (ES:DI) -> SFT
        xor     cx,cx
        mov     es:[di].sf_fsi.pPVDBFil.LowWord,cx                     ;b712094
        mov     es:[di].sf_fsi.pPVDBFil.HighWord,cx                    ;b712094
        mov     es:[di].sf_fsi.sfi_position.HighWord,cx
        mov     es:[di].sf_fsi.sfi_position.LowWord,cx  ; Init. sfi_position to 0
        mov     es:[di].sf_fsi.sfi_hVPB,NULLVPB     ; Zero out sfi_hVPB initially

; fill in consistency bits in sf_flags2 based on the openmode2 bits

        mov     cx,TASKAREA:[bx].opn3s_Mode2
        and     cx,open2_consist_bits           ; isolate consistency bits
        .errnz  (open2_consist_bits -1)
        shl     cx,7
        .errnz (SFF2_Consistency - 0180h)
        or      es:[di].sf_flags2,cx

                                        ;72417 moved from PTDA to TCB
        SetBP_CurrTCB
        test    [bp].TCBPathNameType,PNType_LOCDEV+PNType_PSDEV   ; Character device?
        UnSetBP_CurrTCB
        jz      fsoc04          ; No, skip SFT initialization, go call sharer
        or      es:[di].sf_flags,DEVID_DEVICE ; character device

        SaveReg <ds,si>
        mov     si,CurrTCB
        lds     si,TASKAREA:[si].TCBDevPt
                                        ;72417 end
        mov     es:[di].sf_devptr.Segmt,ds
        mov     es:[di].sf_devptr.Offst,si  ; Set up devptr in sft
        mov     al,byte ptr ds:[si].SDevAtt
        RestoreReg      <si,ds>
        test    al,DEV_CIN OR DEV_COUT          ; is this a console device ?
        jnz     fsoc05

; the sft is for a file, or  a device (but not a console device)
; ss:bx = argframe

fsoc04: test    word ptr ss:[bx].opn3s_Mode2,open2_io_mode
        jz      fsoc05

        mov     ax,ERROR_INVALID_PARAMETER
        stc
        jmp     fsoc75

; sft is for a file, or a device
; if device, sft has been initialised for device, above

                                        ;72417 moved from PTDA to TCB
fsoc05: SetBP_CurrTCB
        test    TASKAREA:[bp].TCBPathNameType, PNType_PSDEV ; is it a pseudo-device?
        UnSetBP_CurrTCB
                                        ;72471
        jz      fsoc10                       ; no

;   for pseudo-devices, we have to request the mutex semaphore

        SaveReg <ds,es>
        CpuMode 386
        FlatContext <DS,ES>, dx
        CCALL32 _KSEMRequestMutex,<<offset FLAT:CharDevSem>,-1>

        CpuMode Reset
        ASSUME  DS:TASKAREA
        ASSUME  ES:NOTHING
        RestoreReg <es,ds>


; BUGBUG  - nagara 5/19/89
; We enter the remote objects into sharing just for the sake of
; supporting FSH_NAMEFROMSFN. (just for the full name we enter them into
; sharing). If we can find a better alternative without too much pain, we
; should remove them from sharing.
;
; We also do not enter named pipes into the sharing set.
;
; The same sort of checking needs to be done in FSD_Close when MFTclose is
; called, and at the end of this routine in case of error.
;

                                        ;72417 moved from PTDA to TCB
fsoc10: SetBP_CurrTCB
        test    [bp].TCBPathNameType,PNType_NMPIPE OR PNType_UNC
        UnSetBP_CurrTCB
                                        ;72417 end
        jnz     fsoc25                  ; Don't do sharing for named pipes
        mov     cx,opbatchbreak OR oplockbreak  ; break oplock or opbatch
        SaveReg <BX,BP>
        CALL32  MFT_Enter,nocheck       ; Enter sft into sharing set
        RestoreReg <BP,BX>              ; BX -> parm frame, BP -> LocalVar frame
        mov     di,CurrTCB
        les     di,TASKAREA:[di].TCBThisSFT ; (ES:DI) -> SFT
        jnc     fsoc20                  ; No problem with access, go route to fs
        mov     cx,fsoc_OpenFlag        ; (cx) = open flags                 ;### PTR B721313  From CP13 B713954
        call    SHARE_ERROR
        jmp     fsoc60                  ; Return error

;
; SS:BX -> parameter frame on stack
; ES:DI -> SFT
;
fsoc20: mov     si,TASKAREA:[CurrTCB]
                                        ;72417 moved from PTDA to TCB
        test    TASKAREA:[si].TCBPathNameType,PNType_LOCFILE OR PNType_REMFILE  ; Local or remote file?
                                        ;72417 end
        jz      fsoc22                  ; No. Don't need to worry about vpb disappearing
        SaveReg <BP>                    ;  because remote drives are attached
        mov     ax,TASKAREA:[si].TCBThishVPB
        mov     es:[di].sf_fsi.sfi_hVPB,ax  ; Set up sfi_hVPB in SFT for files ONLY
        mov     bp,ax                   ; BP = hVPB
        call    IncVPBRef               ; Make sure that we keep this VPB around
        RestoreReg <BP>
;
; If the request is to replace an existing file, we must check to make sure
; that there are no locks on the file.  So if the MFT lock pointer is non-
; zero, we fail the open with ERROR_LOCK_VIOLATION.
;
; NOTE: this code relies on the MFT being set, so is not currently executed
;       for pipes and UNC names.
;
; ES:DI -> SFT
;
fsoc22: test    TASKAREA:[bx].opn3s_Flag,exist_replace ; replace desired?
        jz      fsoc25                  ; no, allow the open to continue

        CpuMode 386

        SaveReg <esi,ds>
        mov     esi,es:[di].sf_MFT

IFDEF   FSSTRICT                        ; internal error if mft is not set
        cmp     esi,SF_MFT_NULL
        jne     SHORT fsoc23
        InternalError <FSD_OpenCreate: MFT is null>
fsoc23:
ENDIF

        FlatContext ds                  ; (DS:ESI) -> MFT entry
        test    ds:[esi].mft_lptr,-1    ; is there a lock pointer?
        RestoreReg <ds,esi>
        ASSUME  DS:TASKAREA
        jz      SHORT fsoc25            ; no, no locks and so no violations
        mov     ax,ERROR_LOCK_VIOLATION ; replace desired but file has locks
        jmp     fsoc90                  ; ==> error

fsoc25: mov     si,TASKAREA:[CurrTCB]
        mov     eax,TASKAREA:[si].TCBThisFSC
        mov     es:[di].sf_FSC,eax      ; sf_FSC is now set up

ifdef SECURITY
        FlatContext <DS>                                                 ;@SEC
        movzx   ecx,_fSec                                                ;@SEC
        mov     fsoc_fSec,cx      ; sav copy on stack to save sel loads  ;@SEC
        or      cx,cx                                                    ;@SEC
        jz      fsoc25c                                                 ;@SEC
        SaveReg <SI,DI>                                                  ;@SEC
        mov     ESI,DWORD PTR ss:[BX].opn3s_Mode                         ;@SEC
        mov     DI, ss:[bx].opn3s_Flag                                   ;@SEC
        ; [WFP_START]  -> file to open                                   ;@SEC
        ; [TCBThisSFT] -> SFT to be used                                 ;@SEC
        ; DI           -> Open Flags                                     ;@SEC
        ; ESI          -> Open Mode                                      ;@SEC
        CALLFAR SecOpenPre                                               ;@SEC
        ; ERROR IN CX since AX IN USE                                    ;@SEC
        RestoreReg < DI,SI>                                              ;@SEC
        jcxz    fsoc25c                   ; No Error, continue           ;@SEC
        mov     ax,cx                     ; Put error where it belongs   ;@SEC
        jmp     fsoc90                    ; Error Go Get outta dodge     ;@SEC
fsoc25c:
        TaskContext <DS>
endif

        CpuMode reset

        cmp     ax,FSC_LOCAL            ; what file system?
        LJE     fsoc30                  ; FAT FS, go call FAT FS worker

;****
;
; The call is for the FSD. Set up the parameters on the stack and call
; FS_OpenCreate.
;
                                        ;72417 moved from PTDA to TCB
        SetBP_CurrTCB
        test    [bp].TCBPathNameType,PNType_PSDEV ; remote device?
        UnSetBP_CurrTCB
                                        ;72417 end
        jnz     fsoc26                  ; yes, go pass dev ptr
        mov     di,TASKAREA:CurrTCB             ; (DI) = current TCB     ;### PTR B720732
        les     di,TASKAREA:[di].TCBThisCDS     ; (es:di) = CDS pointer  ;### PTR B720732
;### PTR B720732        les     di,TASKAREA:[ThisCDS]   ; ES:DI -> CDS
        lea     ax,es:[di].cd_fsi
        push    es
        push    ax                      ; pcdfsi (pointer to fs independent part of CDS)

        lea     ax,es:[di].cd_fsd       ; not remote device, pass pcdfsd
        push    es
        push    ax                      ; pcdfsd (pointer to fs dependent part of CDS)
        jmp short fsoc27

; pass pdevfsd - info about pseudochar device set by FSD in FS_ATTACH call

fsoc26: TaskContext <ds>
                                        ;72417 moved from PTDA to TCB
        mov     si,CurrTCB
        mov     si,TASKAREA:[si].TCBWFP_Start ; (DS:SI) -> device name
                                        ;72417 end
        add     si,DEV_PREFIX_LEN             ; DS:SI -> "devicename"
        mov     ax,DEVTYPE_PSEUDO       ; pseudo-char device
        SaveReg <bx>
        CALLFAR GetDevEntry             ; (DS:SI) -> device
        RestoreReg <bx>
        mov     ax,ERROR_INVALID_PATH
        LJC     fsoc90                  ; removed, go return
    ASSUME DS:NOTHING
        mov     ax,[si].DES_DevFsd.hiword
        mov     [fsoc_devfsd].hiword,ax
        mov     ax,[si].DES_DevFsd.loword
        mov     [fsoc_devfsd].loword,ax
        lea     ax,[fsoc_devfsd]        ; TASKAREA:AX -> devfsd
        push    0                       ; pcdfsi (NULL for device)
        push    0
        push    ss                      ; pdevfsd
        push    ax

fsoc27: TaskContext <ds>                ; Get TASKAREA addressability
        mov     si,TASKAREA:[CurrTCB]   ; DS:SI -> Current TCB
        push    ss
                                        ;72417 moved from PTDA to TCB
        push    TASKAREA:[si].TCBWFP_Start ; pName (Pointer to canonicalized name)
        mov     ax,TASKAREA:[si].TCBCurr_Dir_End
        cmp     ax,-1
        jz      fsoc28                  ; No current directory in pName
        sub     ax,TASKAREA:[si].TCBWFP_Start ; AX = offset into pName of end of curdir
                                        ;72417 end
fsoc28: push    ax                      ; iCurDirEnd (Offset of current dir in pName)
        les     di,TASKAREA:[si].TCBThisSFT     ; ES:DI -> SFT
;
; Set up sfi_size with the size of file requested by the user
;
        mov     ax,TASKAREA:[bx].opn3s_Size.HighWord
        mov     es:[di].sf_fsi.sfi_size.HighWord,ax
        mov     ax,TASKAREA:[bx].opn3s_Size.LowWord
        mov     es:[di].sf_fsi.sfi_size.LowWord,ax
        mov     es:[di].sf_fsi.sfi_type,STYPE_FILE  ; default type
        test    es:[di].sf_flags,SF_FCB             ; Is this SFT for an FCB?
        jz      fsoc28a                             ; No. COntinue.
        or      es:[di].sf_fsi.sfi_type,STYPE_FCB   ; Yes. Set FCB bit
fsoc28a: lea     ax,es:[di].sf_fsi       ; ES:AX -> sf_fsi
        push    es
        push    ax                      ; psffsi (pointer to fs independent part of SFT)
        lea     ax,es:[di].sf_fsd
        push    es
        push    ax                      ; psffsd (pointer to fs dependent part of SFT)
        push    TASKAREA:[bx].opn3s_Mode2 ; High word of fhandflag - (OpenMode)
        test    byte ptr [fsoc_execonly],EXECOPEN    ; exec_only BN040
        jz      fsoc28a1                             ; exec_only BN040
        or      TASKAREA:[bx].opn3s_Mode,3           ; exec_only BN040
fsoc28a1:                                            ; exec_only BN040
        push    TASKAREA:[bx].opn3s_Mode  ; Low word of fhandflag
        push    TASKAREA:[bx].opn3s_Flag ; openflag (actions to be taken)
        push    ss
        lea     ax,[fsoc_ActionTaken]
        push    ax                      ; pAction (Location to place action taken)
                                        ;72417 moved from PTDA to TCB
        SetBP_CurrTCB
        mov     al,TASKAREA:[bp].TCBPathNameType
        UnSetBP_CurrTCB
                                        ;72417 end
        and     ax,PNType_NEWFILE       ; ax = 0 or 0x0040
        or      ax,TASKAREA:[bx].opn3s_Attrs
        push    ax                      ; attr (file attributes for CREATE)
        push    TASKAREA:[bx].opn3s_EABufPtr.Segmt
        push    TASKAREA:[bx].opn3s_EABufPtr.Offst    ; pEABuf (pointer to EABuf)
        lea     ax,fsoc_fgenflag        ;
        push    ss
        push    ax

;aa04936CpuMode 386
;aa04936SaveReg <ds,es>
;aa04936FlatContext <ds,es>
;aa04936cmp     _fPerfview,0            ; check if perfview is up      ;b712094
;aa04936je      short fsoc28a1          ;                              ;b712094
;aa04936mov     ecx,_pPTDACur           ; (EDX) = pointer to current PTDA
;aa04936mov     esi,_pTCBCur            ; (EDI) = pointer to current TCB
;aa04936CCALL32 _PVWCreateInstance_Fil,<ecx,esi>
                                ; Create Perfview per-process data blk
;aa04936fsoc28a1:                                                              ;b712094
;aa04936        CpuMode Reset
;aa04936        ASSUME  DS:TASKAREA
;aa04936        ASSUME  ES:NOTHING
;aa04936        RestoreReg <es,ds>

        les     di,es:[di].sf_FSC
        call    es:[di].FS_OPENCREATE   ; Call the FSD

ifdef SECURITY
        mov     cx,[fsoc_ActionTaken]   ; CX = Action taken by FSD     ;@SEC
;                                                                      ;@SEC
; The operation was successful for the FSD.                            ;@SEC
; Call Security Subsystem (if necessary) to validate user has access   ;@SEC
        cmp     fsoc_fSec,0             ; is security enabled?         ;@SEC
        jz      fsc28a2                 ; no                           ;@SEC
        FlatContext <DS>                                               ;@SEC
        mov     cx,[fsoc_ActionTaken]   ; CX = Action taken by FSD     ;@SEC
        ; [TCBThisSFT]                                                 ;@SEC
        ;  AX   - Return Code                                          ;@SEC
        ;  CX   - Action Taken                                         ;@SEC
        ;  DS   - FLAT                                                 ;@SEC
        mov     bx,[fsoc_Args]                                         ;@SEC
        mov     di,ss:[bx].opn3s_Flag                                  ;@SEC
        mov     esi,DWORD PTR ss:[bx].opn3s_Mode                       ;@SEC
        CALLFAR SecOpenPost                                            ;@SEC
        TaskContext <DS>,di                                            ;@SEC
                                                                       ;@SEC
fsc28a2:                                                               ;@SEC
endif
        dec     ax
        sub     ax,-1                   ; Set carry if ax != 0
        mov     cx,[fsoc_ActionTaken]   ; CX = Action taken by FSD
        mov     di,CurrTCB
        les     di,TASKAREA:[di].TCBThisSFT     ; ES:DI -> SFT
        LJC     fsoc90                  ; Error. Remove file from sharing set
;
; The operation was successful for the FSD.
; Set SF_ISNET bit for remote or UNC names in sf_flags.
; Set the sf_devptr field to zero so that GetHandleInfo(RM) does not barf.
; Map sfi_type info into sf_flags.
;
; The object can only be of one type (i.e. file, device or named pipe).
; If the FSD set more than one of the bits in sfi_type, then we InternalError.
;

        SaveReg <es,di>
        les     di,es:[di].sf_FSC       ; ES:DI -> FSC
        les     di,es:[di].FS_ATTRIBUTE ; es:di ->FS_ATTRIBUTE
        mov     ax,word ptr es:[di]
        test    ax,FS_ATTR_UNC or FS_ATTR_REMOTE
        RestoreReg <di,es>              ; ES:DI -> SFT
        jz      fsoc28b                         ; Not a remote or UNC object
        or      es:[di].sf_flags,SF_ISNET   ; Mark this as "network object"
        mov     es:[di].sf_devptr.Segmt,0
        mov     es:[di].sf_devptr.Offst,0   ; Zero out device pointer
                                        ;72417 moved from PTDA to TCB
        SetBP_CurrTCB
        test    TASKAREA:[bp].TCBPathNameType,PNType_UNC
        UnSetBP_CurrTCB
                                        ;72417 end
        jz      fsoc28b                 ; Not a UNC object
        or      es:[di].sf_flags2,sff2_UNC  ; mark this as UNC object
;
; Make sure sf_flags defaults to file type
;
fsoc28b: and    es:[di].sf_flags,NOT (DEVID_DEVICE OR SF_PIPE OR SF_NMPIPE)
        mov     ax,es:[di].sf_fsi.sfi_type      ; ax = sft type
    .errnz  STYPE_FILE
        and     ax,STYPE_MASK                   ; Mask out irrelevant bits
        or      ax,ax                           ; Is it a file?
        jz      fsoc29                          ; Yes, do nothing
        cmp     ax,STYPE_DEVICE                 ; Is it a device?
        jne     fsoc28c                         ; No, check for named pipe
        or      es:[di].sf_flags,DEVID_DEVICE   ; Yes, set device flag
        jmp     short fsoc29


fsoc28c: cmp   ax,STYPE_NMPIPE                 ; is it a named pipe?
        LJNE    fsocie                          ; no; what is it????
        or      es:[di].sf_flags,SF_PIPE OR SF_NMPIPE ; yes, set pipe flags
;
; If an OPEN was done, then this SFT needs to be updated with information
; from other instances of this file.
; If file was CREATEd or REPLACEd, then we need to update the sfi_size field
; in all the existing SFTs for the file.
; Since this is for an FSD, we need to make sure that we use the correct
; sub-functions to pass to ShSU so that we do not modify any of the sf_fsd
; fields in the SFT.
;
; CX = Action performed (OPEN, CREATE or REPLACE)
;
fsoc29: mov     ax,5                    ; Assume update size of existing SFTs
        cmp     cx,file_exist           ; Was existing file created or replaced?
        jne     fsoc50                  ; Yes. Assumption was good.
        mov     ax,4                    ; No. Copy info from existing SFT into this one
        jmp     fsoc50                  ; Update the SFTs

;****
;
; This is for the FAT file system
;
fsoc30:
;aa04936fsoc30: CpuMode 386
;aa04936SaveReg <ds,es>
;aa04936FlatContext <ds,es>
;aa04936cmp     _fPerfview,0            ; check if perfview is up      ;b712094
;aa04936je      short fsoc31            ;                              ;b712094
;aa04936mov     edx,_pPTDACur           ; (EDX) = pointer to current PTDA
;aa04936mov     esi,_pTCBCur            ; (EDI) = pointer to current TCB
;aa04936CCALL32 _PVWCreateInstance_Fil,<edx,esi>
;aa04936fsoc31:                                                                ;b712094
                                        ; Create Perfview per-process data blk
;aa04936CpuMode Reset
;aa04936ASSUME  DS:TASKAREA
;aa04936ASSUME  ES:NOTHING
;aa04936RestoreReg <es,ds>


; ShutdownGate  function name, exit label, seg with FSC segment (DS or ES)

        ShutdownGate  DOS_OpenCreate, fsoc35, DS

; the above jumps to fsoc35 on completion

;  ES:DI  = SFT
; 'NC' if successful operation
;       CX = Action performed (OPEN, CREATE or REPLACE)
;       BX = 1 if there are need eas for this file
;          = 0 if no need eas ( or no eas)
; 'C' if error
;       AX = error code
;
;fsoc35: TaskContext <ds>                             ;#84315
fsoc35:                                               ;#84315
        mov     es:[di].sf_fsd.sfdFAT_bRAReads,1H     ;149034

ifdef SECURITY
        ; Set AX to zero if no error                                  ;@SEC
        jc      fsoc36                                                ;@SEC
        xor     ax,ax                   ; AX = Zero if no error       ;@SEC
                                                                      ;@SEC
        ; Call Security to notify of open status (if necessary)       ;@SEC
fsoc36:                                                               ;@SEC
        cmp     fsoc_fSec,0                                           ;@SEC
        jz      fsoc38                  ;skip security                ;@SEC
        FlatContext <DS>                                              ;@SEC
        SaveReg <di,esi>                                              ;@SEC
        mov     si,fsoc_Args            ; get argument frame          ;@SEC
        mov     di,ss:[si].opn3s_Flag                                 ;@SEC
        mov     esi,DWORD PTR ss:[si].opn3s_Mode                      ;@SEC
fsoc37: CALLFAR SecOpenPost                                           ;@SEC
        ; ES:DI,CX,BX preserved                                       ;@SEC
        RestoreReg <esi,di>                                           ;@SEC
                                                                      ;@SEC
fsoc38:                                                               ;@SEC
        or      ax,ax                   ; Check Return Code           ;@SEC
        jnz     fsoc90                  ; Error. Remove file from sharing set. @SEC
else
        jc      fsoc90                  ; Error. Remove file from sharing set.
endif
        TaskContext <ds>                              ;#84315
        mov     fsoc_fgenflag,bx        ; store the need ea info
;
; The operation was successful for the FAT file system
;
; If an OPEN was done, then this SFT needs to be updated with information
; from other instances of this file.
; If file was CREATEd or REPLACEd, then we need to update the sfi_size field
; in all the existing SFTs for the file.
; We copy over the sf_fsd fields as well.
;
; CX = Action performed (OPEN, CREATE or REPLACE)
;
fsoc40: mov     ax,2                    ; Assume update size of existing SFTs
        cmp     cx,file_exist           ; Was existing file created or replaced?
        jne     fsoc50                  ; Yes. Assumption was good
        mov     ax,3                    ; No. Copy info from existing SFT into
                                        ; this one

; call the device driver for open if this is a device.
; NOTE that fillDeviceSFT is not called here; it is called by DosOpenCreate
; and not called for FSD now. Obviously NOT ALL fields tampered by FillDeviceSFT
; need to be tampered with by an FSD. SO SHOULD FSD FILL UP THE RELEVANT FIELDS
; IN THE CASE OF A DEVICE ?

; *** pipe and net stuff will not call dev_open_sft since they
;   will fail the DEVID_DEVICE test and dev_oc_sft doesn't do anything for
; remote files (remote and UNC also).

fsoc50: test    es:[di].sf_flags,DEVID_DEVICE ; Character device?
        jz      fsoc52                      ; Not a device. Set SFT for file.
        CALLFAR Dev_Open_SFT      ;148006     Try and open the device
        jc      fsoc90                      ; error in device open - remove
; check NeedEAS if the action is exist_open and there are need eas in the file
; and the PTDA var KnowEAS is not set, then we should not allow the user to open
; the file; If the user is allowed this open, we will lose eas unnecessarily.

fsoc52: cmp     cx,file_exist           ;
        jne     fsoc55
        test    fsoc_fgenflag,-1        ;
        jz      fsoc55                  ;
; test for TCB variable to find out whether the app is old or knows about eas

        push    bx
        mov     bx,CurrTCB              ;
        test    TASKAREA:[bx].TCBNewFlags,TCBKNOWEAS
        pop     bx                      ;
        jz      fsoc100                 ; old app; check for the presence of
                                        ; need eas
;
; Update the relevant SFTs.
; AX = sub-function code for ShSU
;
                                            ; sft from sharing set
fsoc55: SaveReg <CX>
        call    ShSU                    ; Update the SFTs
        RestoreReg <CX>                 ; CX = action taken for create

ifdef PERFVIEW

        CpuMode 386                                                    ;aa04936
        SaveReg <ds,es>                                                ;aa04936
        SaveReg <ax>                                                   ;46691
        mov    ax,es                                                   ;46691

        FlatContext <ds,es>                                            ;aa04936
        cmp     _fPerfview,0            ; check if perfview is up      ;aa04936
        je      short fsoc57            ;                              ;aa04936

        mov     es,ax                                                  ;46691

        test    es:[di].sf_flags,DEVID_DEVICE   ; check if device      ;46691
        jnz     short fsoc57            ; not a file so don't make call;46691
        ; only get data block for files                                ;46691
        FlatContext <es>                                               ;46691
        SaveReg <EAX,CX,EDX,ESI>                                                   ;aa04936
        mov     eax, USE_TCB            ;                              ;aa05408
        mov     edx,_pPTDACur           ; (EDX) = pointer to current PTDA ;aa04936
        mov     esi,_pTCBCur            ; (EDI) = pointer to current TCB ;aa04936
        CCALL32 _PVWCreateInstance_Fil,<edx,esi,eax>                   ;aa5408
        RestoreReg <ESI,EDX,CX,EAX>      ;                              ;aa04936
fsoc57:                                                                ;aa04936
                                        ; Create Perfview per-process data blk
        CpuMode Reset                                                  ;aa04936
        ASSUME  DS:TASKAREA                                            ;aa04936
        ASSUME  ES:NOTHING                                             ;aa04936
        RestoreReg <ax>                                                ;46691
        RestoreReg <es,ds>                                             ;aa04936

endif ;PERFVIEW

        clc                             ; Restore flag to indicate no error

fsoc60: pushf
                                        ;72417 moved from PTDA to TCB
        SetBP_CurrTCB
        test    TASKAREA:[bp].TCBPathNameType,PNType_PSDEV   ; pseudo-device?
        UnSetBP_CurrTCB
                                        ;72417 end
        jz      fsoc70                        ; no

;   For pseudo-devices, we have to release the mutex semaphore

        SaveReg <AX>
        CpuMode 386
        FlatContext <ds,es>,ax
        mov        ebx, offset FLAT:CharDevSem
        CCALL32   _KSEMReleaseMutex <ebx>
;       mov        edx,ebx
;       CALL32     KSEMReleaseMutex

        CpuMode Reset
        TaskContext <DS>
        RestoreReg <AX>

fsoc70: popf
fsoc75: LeaveProc
        ret


;
; We got an error. This means that we have to remove the SFT from the
; sharing set if it is not for a named pipe or a remote object.
;
fsoc90: TaskContext <DS>
        SaveReg <AX>                    ; Save any error code
        mov     di,CurrTCB
        les     di,TASKAREA:[di].TCBThisSFT ; (ES:DI) -> SFT
                                        ;72417 moved from PTDA to TCB
        SetBP_CurrTCB
        test    [bp].TCBPathNameType,PNType_LOCFILE OR PNType_REMFILE  ; Local or remote file?
        UnSetBP_CurrTCB
                                        ;72417 end
        jz      fsoc92                  ; No. Don't have any VPBs
        SaveReg <BP>
        mov     bp,es:[di].sf_fsi.sfi_hVPB
        call    DecVPBRef               ; We can discard the VPB if it is not in use
        RestoreReg <BP>
                                        ;72417 moved from PTDA to TCB
fsoc92: SetBP_CurrTCB
        test    [bp].TCBPathNameType,PNType_NMPIPE OR PNType_UNC
        UnSetBP_CurrTCB
                                        ;72471 end

                                        ; Was this entered in the sharing set?
        jnz     fsoc93                  ; No. Don't try to remove it from the MFT.
        mov     bx,-1                   ; no handle - we don't need to bother
; about other references to this handle since nobody could have duplicated this
; handle ; so we need not pass any handle to MFTclose

        call    MFTclose
fsoc93: RestoreReg <AX>
;
; AX = error code
;
; For the 3xbox, we need to do some error mapping if the error code returned
; is ERROR_OPEN_FAILED. If the OPEN failed, then we map to ERROR_FILE_NOT_FOUND;
; If the CREATE failed, then we map to ERROR_FILE_EXISTS. This is valid since
; that is the only time that this error code should be returned (i.e. when the
; caller told us to fail the operation if the condition was true).
;
; The algorithm that we use is a follows:
;
;   if ((3xbox) && (error = open_failed) {
;       if (!(OpenFlags & 0x000F)
;           error = file_exists
;       else if (!(OpenFlags & 0x00F0)
;           error = file_not_found
;   }
;

        cmp     [ProcType],PT_REALMODE  ; 3xbox?
        jne     fsoc99                  ; No. No mapping to do.
        cmp     ax,ERROR_OPEN_FAILED
        jne     fsoc99                  ; No mapping of error codes necessary
        test    fsoc_OpenFlag,exist_mask    ; FAIL if file exists?
        jnz     fsoc95                  ; No. Continue checking.
        mov     ax,ERROR_FILE_EXISTS    ; Yes. Map to file_exists.
        jmp     short fsoc99

fsoc95: test    fsoc_OpenFlag,nexist_mask   ; FAIL if file does not exist?
        jnz     fsoc99                  ; No. Return open_failed.
        mov     ax,ERROR_FILE_NOT_FOUND
fsoc99: STC                             ; Return error indication and error code
        jmp     fsoc60
;  there were need eas for the file that was opened just now, and the app is
; an old app that doesnot know about EAS; we have to fail the request
; es:di -> SFT
; TCBThisSFT set up

fsoc100: mov    es:[di].sf_ref_count,1  ; FSD_Close is going to decrement it
        mov     bx,-1                   ; no handle
        call    FSD_Close
        mov     ax,ERROR_ACCESS_DENIED
        stc
        jmp     fsoc60

fsocie: InternalError <FSD_OpenCreate: Bad sfi_type set by FSD>

EndProc     FSD_OpenCreate


;***    Share_Error - handle a sharing violation
;
;       If SFT is FCB or compatibility mode gens INT 24 error.
;       If and only if 3xBox, never generate hard error for prot mode apps.
;
;       ENTRY   ES:DI points to SFT.
;               AX has error code
;               CX has open flags                                           ;### PTR B721313  From CP13 B713954
;
;       EXIT    TCBForce_Flg = FF_RTRY if we are to retry the operation
;               AX = ERROR_SHARING_VIOLATION
;
;       USES    AX, BX, CX, DX, SI, Flags

Procedure SHARE_ERROR,HYBRID
        SegAssert SS, <DS>
        ASSUME  DS:TASKAREA, ES:NOTHING

        CMP     [ProcType],PT_REALMODE  ; Are we the 3xBox?
        JNE     se80                    ; not 3xBox, go report error ;### PTR B721313  From CP13 B713954
;####   JNE     NO_HARD_ERR             ; not 3xBox, go report error ;### PTR B721313  From CP13 B713954

        TEST    ES:[DI].sf_flags,SF_FCB
        JNZ     HARD_ERR                ; It's an FCB, go call Share_Violation

        MOV     CL,BYTE PTR ES:[DI.sf_fsi.sfi_mode]
        AND     CL,open_sharing_mode    ; sharing_compat?
.errnz  sharing_compat
        jnz     NO_HARD_ERR             ; no, go return

;       We're running as the 3xBox AND
;       file is fcb OR files was opened in compatibility mode

HARD_ERR: mov    bx,CurrTCB
        mov     bx,TASKAREA:[bx].TCBThishVPB     ; BX = hVPB
        mov     es:[di].sf_fsi.sfi_hVPB,bx  ; Set up hVPB in sft
        SaveReg <AX>
        call    Share_Violation
        RestoreReg <AX>                 ; Restore error code
NO_HARD_ERR:
        STC
        ret

se80:   test    cx,exist_mask           ; FAIL if file exists?        ;### PTR B721313  From CP13 B713954
        jnz     NO_HARD_ERR             ; no, do not remap error code.;### PTR B721313  From CP13 B713954
                                                                      ;### PTR B721313  From CP13 B713954
        mov     ax,ERROR_OPEN_FAILED    ; Yes. Map to file_exists.    ;### PTR B721313  From CP13 B713954
        jmp     short NO_HARD_ERR                                     ;### PTR B721313  From CP13 B713954

EndProc SHARE_ERROR

HIGH2CODE  ENDS


        FARCODE HIGH4
HIGH4CODE       SEGMENT

;***    FillSFTFromDirEnt - Fill in SFT from FAT dir entry
;
;       ENTRY   ThishVPB points to hVPB if file
;               [ThisSFT] points to SFT being used
;               [CurBuf+2]:BX points to start of directory entry
;
;       EXIT    sf_ref_count and sf_fsi.sfi_mode fields not altered
;               sf_flags high byte = unchanged
;               sf_flags Bit 6 set (not dirty or not EOF)
;               fsi.sfi_DOSattr, sf_fsi.sfi_mdate, sf_fsi.sfi_mtime,
;                       sf_name set from entry
;               sf_fsi.cdate sf_fsi.ctime sf_fsi.adate sf_fsi.atime = 0
;               sf_fsi.sfi_position = 0
;               sfdFAT_firFILEclus sf_fsi.sfi_size set from entry
;               sf_devptr = [ThisDPB]
;               sfdFAT_cluspos = 0
;               sfdFAT_lstclus = sf_firFILEclus
;               sfdFAT_dirsec sf_dirpos set
;               sfdFAT_EAHandle set
;
;       USES    AX, CX, DX, DI, ES, Flags
;
Procedure   FillSFTFromDirEnt,NEAR
    ASSUME DS:NOTHING, ES:NOTHING, SS:TASKAREA

        SaveReg <DS,BP,SI>
        lea     si,[bx].dir_firstfile   ; SI -> dir_firstfile field for object
        mov     di,CurrTCB
        les     di,TASKAREA:[di].TCBThisSFT
;
; Generate and store attribute
;
        mov     bp,CurrTCB
        mov     ds,word ptr [bp].TCBCurBuf+2 ; DS:BX -> directory entry in buffer
    ASSUME      DS:NOTHING
        mov     bp,TASKAREA:[bp].TCBThishVPB ; BP = hVPB
        mov     al,[bx.dir_attr]           ; If file, get attrib from dir entry

; This is either being smart or lazy, but since a lot of the following code
; assumes a certain order of filling in the SFT and I am changing where in
; the SFT that the DOS file attributes reside, I will fill in the DOS
; attributes using the "full offset definition" gotten from using the struc
; definitions, then let the rest of the procedure go on as normal.


        mov     es:[di].sf_fsi.sfi_DOSattr,al
        xor     ax,ax
        lea     di,[di].reserved     ; Skip to reserved field(former sf_attr
        stosb                        ; field), now ES:DI -> sf_flags
;
; Generate and store flags word
;
        or      al,DEVID_FILE_CLEAN
        or      ax,word ptr es:[di]   ; drop in existing bits from flag field
    .errnz      sf_flags-(reserved+1)
        stosw                         ; sf_flags, ES:DI -> sf_flags2

        add     di,2
;
; Store 0:hVPB in sf_devptr field
;
        mov     ax,bp                   ; AX = hVPB
    .errnz      sf_devptr-(sf_flags2+2)
        stosw                           ; store hVPB
        xor     ax,ax
        stosw                           ; zero out segment
;
; Generate pointer to, generate and store first cluster
;
        PUSH    SI              ; Save pointer to dir_firstfile
    .errnz      sf_FSC-(sf_devptr+4)
        ADD     DI,sf_fsd.sfdFAT_firFILEclus - sf_FSC   ; ES:DI -> sfdFAT_firFILEclus
        MOVSW                   ; dir_firstfile -> sfdFAT_firFILEclus
                                ; DS:SI -> dir_size_l, ES:DI->sfdFAT_cluspos
;
; Store VPB referent
;
    .errnz      sfdFAT_cluspos-(sfdFAT_firFILEclus+2)
        ADD     DI,sf_fsi.sfi_hVPB-sf_fsd.sfdFAT_cluspos    ; ES:DI -> sfi_hVPB
        MOV     AX,BP
        STOSW

;
; Copy time/date of last modification
;
        XOR     AX,AX
        SUB     SI,dir_size_l - dir_time        ; DS:SI->dir_time

        STOSW                           ; sfi_ctime = 0
    .errnz      sfi_ctime-(sfi_hVPB+2)
        STOSW                           ; sfi_cdate = 0
    .errnz      sfi_cdate-(sfi_ctime+2)
        STOSW                           ; sfi_atime = 0
    .errnz      sfi_atime-(sfi_cdate+2)
        STOSW                           ; sfi_adate = 0
    .errnz      sfi_adate-(sfi_atime+2)
        MOVSW                           ; sfi_mtime = dir_time
    .errnz      sfi_mtime-(sfi_adate+2)
        MOVSW                           ; sfi_mdate = dir_date
    .errnz      dir_date-(dir_time+2)
    .errnz      sfi_mdate-(sfi_mtime+2)

                                ; DS:SI -> dir_firstfile, ES:DI -> sfi_size
;
; Generate and store file size
;
    .errnz      dir_firstfile-(dir_date+2)
        LODSW                   ; skip dir_firstfile, DS:SI -> dir_size_l
    .errnz      dir_size_l-(dir_firstfile+2)
        LODSW                   ; dir_size_l in AX , DS:SI -> dir_size_h
        MOV     CX,AX           ; dir_size_l in CX
    .errnz      dir_size_h-(dir_size_l+2)
        LODSW                   ; dir_size_h (size AX:CX), DS:SI -> ????
        XCHG    AX,CX
    .errnz      sfi_size-(sfi_mdate+2)
        STOSW                   ; Low word of sfi_size
        XCHG    AX,CX
        STOSW                   ; High word of sfi_size
                                ; ES:DI -> sfi_position
;
; Initialize position to 0
;
        XOR     AX,AX
    .errnz      sfi_position-(sfi_size+4)
        STOSW
        STOSW                   ; sfi_position. ES:DI -> sfi_UID
        SUB     DI,sf_fsi.sfi_UID - sf_fsd.sfdFAT_cluspos
                                ; ES:DI -> sfdFAT_cluspos
;
; Generate cluster optimizations for files
;
        STOSW                   ; sfdFAT_cluspos
        MOV     AX,[BX.dir_firstfile]
    .errnz      sfdFAT_lstclus-(sfdFAT_cluspos+2)
        STOSW                   ; sfdFAT_lstclus
        mov     si,CurrTCB
        mov     si,TASKAREA:word ptr [si].TCBCurBuf     ; DS:SI->buffer header
        MOV     AX,word ptr [SI.buf_sector]
    .errnz      sfdFAT_dirsec-(sfdFAT_lstclus+2)
        STOSW                   ; sfdFAT_dirsec
        MOV     AX,word ptr [SI.buf_sector]+2
        STOSW                   ; sfdFAT_dirsec + 2
        MOV     AX,BX
        ADD     SI,BUFINSIZ     ; DS:SI-> start of data in buffer
        SUB     AX,SI           ; AX = BX relative to start of sector
        MOV     CL,SIZE dir_entry
        DIV     CL
    .errnz      sfdFAT_dirpos-(sfdFAT_dirsec+4)
        STOSB                   ; sfdFAT_dirpos
        MOV     AX,[BX.dir_EAhandle]
    .errnz      sfdFAT_EAHandle-(sfdFAT_dirpos+1)
        STOSW                   ; sfdFAT_EAhandle
    .errnz      sfdFAT_name-(sfdFAT_EAHandle+2)

;
; Copy in the object's name
;
        MOV     SI,BX           ; DS:SI points to dir_name
        MOV     CX,SFNAMELEN
    REP MOVSB                   ; sf_name
        POP     SI              ; recover DS:SI -> dir_firstfile
        RestoreReg <SI,BP,DS>   ; Restore BP of entry
        CLC
        ret
EndProc FillSFTFromDirEnt


;***    FillDeviceSFT - Fill in the SFT for the device
;
;       ENTRY   [ThisSFT] points to SFT being used
;               [WFP_Start] points to the buffer in TASKAREA where the
;                   canonicalized name of the device is present
;               [DevPt] points to device header
;
;       EXIT    sf_ref_count and sf_fsi.sfi_mode fields not altered
;               sf_flags high byte = unchanged
;               sf_flags set up from device attributes (bit 6 is set as well)
;               sf_fsi.sfi_cdate, sf_fsi.sfi_ctime set from clock
;               sf_name set from name at [WFP_Start]
;               sf_fsi.sfi_position = 0
;               sf_fsi.DOSattr = 0
;               sf_devptr = [DevPt]
;               sf_fsd field zeroed out (sfdFATFS structure)
;
;       USES    AX, CX, DX, SI, Flags
;
Procedure   FillDeviceSFT,NEAR
    ASSUME DS:TASKAREA, ES:NOTHING, SS:TASKAREA

        SegAssert SS,<DS>,"FillDeviceSFT"
        SaveReg <DI,ES>
        mov     di,CurrTCB
        les     si,TASKAREA:[di].TCBThisSFT
        xor     ax,ax
        mov     es:[si].sf_fsi.sfi_DOSattr,al   ; sfi_DOSattr = 0
        lea     di,[si].reserved
        stosb                                   ; reserved = 0
        mov     cx,(sfi_UID - sfi_hVPB)
    .errnz (sfi_UID - sfi_position - 4)
        lea     di,[si].sf_fsi.sfi_hVPB     ; Zero out hVPB, date, time, size
        rep     stosb                           ; and position
        lea     di,[si].sf_fsi.sfi_mtime
;
; We need to fill in the time and date for devices as well since we often
; treat them like files, and allow a user to get the file information for a
; device.
;
        CALLFAR Date16
        xchg    ax,dx                       ; AX = time, DX = date
        stosw                               ; sfi_mtime
        xchg    ax,dx                       ; AX = date, DX = time
        stosw                               ; sfi_mdate
        SaveReg <SI>
        lea     di,[si].sf_flags
                                            ;72417 moved from PTDA to TCB
        mov     si,CurrTCB
        lds     si,TASKAREA:[si].TCBDevPt
                                            ;72417 end
    ASSUME DS:NOTHING
        xor     ax,ax
        mov     al,byte ptr [si].SDevAtt
        or      ax,DEVID_DEVICE or DEVID_DEVICE_EOF
        and     al,not DEVID_DEVICE_RAW
        or      ax,word ptr es:[di]         ; Drop in existing sf_flags bits
        stosw                               ; sf_flags

        xor     ax,ax
    .errnz (sf_flags2 - sf_flags - 2)
        stosw                               ; sf_flags2

        mov     ax,si
    .errnz (sf_devptr - sf_flags2 - 2)
        stosw                               ; sf_devptr.Offst
        mov     ax,ds
        stosw                               ; sf_devptr.Segmt
        RestoreReg <SI>
        TaskContext DS
        xor     ax,ax
        lea     di,[si].sf_fsd
        mov     cx,SIZE sfdFATFS
        rep     stosb                       ; Zero FAT FS dependent part
        lea     di,[si].sf_fsd.sfdFAT_name
        mov     cx,DEVNAMELEN+1
                                            ;72417 moved from PTDA to TCB
        mov     si,CurrTCB
        mov     si,TASKAREA:[si].TCBWFP_Start  ; DS:SI -> "\DEV\<device name>"
                                            ;72417 end
        add     si,5                        ; Skip over "\DEV\"
fds10:  lodsb
        stosb
        or      al,al
        loopnz  fds10                       ; Fill up field until end of string
        RestoreReg <ES,DI>
        ret
EndProc     FillDeviceSFT


;***    GetBufBack - retrieve a directory sector
;
;       GetBufBack will get back a buffer sector which had been released
;       to allow other buffer system operations to occur.
;
;       ENTRY   ES:BP points to VPB
;               BX points relative to beginning of buffer to dir. entry
;               CX:DX = sector number desired
;
;       EXIT    [CurBuf] contains a pointer to the buffer
;               ES:BP points to VPB
;               [CurBuf+2]:BX points to directory entry
;               [CurBuf+2]:SI points to above dir_firstfile
;               Carry set if error rereading the buffer.
;
;       USES    AX, BX, DX, SI, BP, ES, Flags
;
;       EFFECTS Switches Context
;


Procedure   GetBufBack,NEAR
        SegAssert SS,<DS>
        ASSUME DS:TASKAREA, ES:NOTHING

        chkvselhd es,bp
        PUSH    BX
        push    bp
        mov     bp,CurrTCB
        mov     [bp].TCBAllowed,ALLOWED_FAIL + ALLOWED_RETRY
        pop     bp
        XOR     AL,AL
        CALLFAR GetBuffr        ; Get sector back
        POP     BX              ; Get offset back
        jc      gbb1            ; error, go return
        call    SET_BUF_AS_DIR
        push    bp
        mov     bp,CurrTCB
        mov     ax,word ptr [bp].TCBCurBuf
        pop     bp
        ADD     BX,AX           ; Correct it for new buffer
        MOV     SI,BX
        lea     si,[si].dir_firstfile   ; SI -> dir_firstfile for entry
        CLC
gbb1:   ret
EndProc GetBufBack

HIGH4CODE       ENDS


        END
