;       SCCSID = @(#)sftio.asm  6.11 92/02/22
SCCSID  equ     "@(#)sftio.asm  6.11 92/02/22"
        PAGE    ,132
TITLE   SFTIO - Kernel SFT based file I/O interface

;
;  Title:
;
;       SFTIO - a kernel callable SFT level I/O package,
;               specifically implemented as an interface for the loader
;
;       Copyright (c) Microsoft Corporation 1989
;
;  Description:
;
;       SFTIO contains the following loader visible
;       kernel file I/O routines:
;
;               _IOSftOpen
;               _IOSftWriteAt   - not used by loader, only hotfix
;               _IOSftReadAt
;               _IOSftTransPath
;               _IOSftClose
;               _SftFileSize    - not used by loader, only hotfix
;               _Canon          - used by sem
;
;       It also contains the worker functions used by these
;       routines.
;
;***********************************************************************;BN040;
;  29Jul93 - J.M.Hare    defect 71358                                   ;BN040;
; Add propogating of DOSFLAG through files system for exec_only test.   ;BN040;
;***********************************************************************;BN040;
;  12Aug93 - K. Luo      defect 72625 : SFT leak                        ;
;  06Dec94 -             defect 105627: @SEC  Skip around setting
;                                       ldrpFilenameBuf if called by security
;  11/27/95- MLM         defect 72417 : moved Sattrib from PTDA to TCB


.xlist
include dosseg.inc
include basemaca.inc
include osmaca.inc
include fnofs.inc
include osconst.inc
.xcref
include dossymc.inc
include mi.inc
include sft.inc
include infoseg.inc
include except.inc
include sigdef.inc
include pgexport.inc
include vmexport.inc
include tkexport.inc
include screen.inc
include sem.inc
include curdir.inc
include dirent.inc
include find.inc
include tkptda.inc
include error.inc
include argframe.inc
include fsc.inc
ifdef SECURITY
include secure2.inc
endif
.cref
.list

        CpuMode 386
        ModName , FNO_SFTIO_ASM

        ReferFlat _pTCBCur,dword
        ReferFlat _pPTDACur,dword
        ReferFlat _ldrpFileNameBuf,dword
        ReferFlat _ldr16pFileNameBuf,dword

        EXTRN _SELLdrDesc:NEAR
        EXTRN _SELFreeGDT:NEAR
        EXTRN _SELVirtToLin:NEAR

        EXTRN16 SFNAlloc
        EXTRN16 SFLinkFree
        EXTRN16 SFFromSFN
        EXTRN16 SFLock
        EXTRN16 SFUnlock
        EXTRN16 TransPathCnvPathChars
        EXTRN16 RlseBuffr
        EXTRN16 sft_lseek
        EXTRN16 FSD_ChgFilePtr
        EXTRN16 FSD_NewSize
        EXTRN16 FSD_OpenCreate
        EXTRN16 FSD_Commit
        EXTRN16 FSD_Write_NT
        EXTRN16 FSD_Read
        EXTRN16 FSD_Close
        EXTRN16 w_Canon
        EXTRN16 GetTempBuffer
        EXTRN16 FreeTempBuffer

        EXTRN32 _KSEMRequestMutex
        EXTRN32 _KSEMReleaseMutex


        FARCODE HIGH32
HIGH32CODE SEGMENT



;***EP  _IOSftOpen      - open a file
;
;       _IOSftOpen is a C callable routine to allocate an SFT and
;       open a file.  No JFN is allocated.
;
;       ENTRY   [esp]   ret addr
;               [esp+4] 32-bit near pointer to name of file to open
;               [esp+8] dword of file modes
;               [esp+12] dword of open flags
;               [esp+16] 32-bit near addr of location to store SFN in
;               [esp+20] pointer to transpath buf
;
;       EXIT    eax = error code
;
Procedure _IOSftOpen
        ASSUME  DS:FLAT, ES:FLAT, FS:NOTHING, GS:NOTHING, SS:NOTHING

        ArgVar  pszFname,DWORD          ; pointer to file name
        ArgVar  FileMode,DWORD          ; share, access, etc. mode
        ArgVar  OpenFlag,DWORD          ; open flags (fail if !exist, etc.)
        ArgVar  pSFN,DWORD              ; pointer to SFN to use
        ArgVar  pLocalBuf,DWORD         ; pointer to buffer for TRANSPATH

        LocalVar   dummycds,<SIZE curdir>
        LocalVar   tcbsavebuf,TCBIOCopySize
        LocalVar   SelTemp,DWORD                 ; alias selector to pszFname
        LocalVar   OpenArgFrame,<size Open3Struc>
        LocalVar   TempBufferOff,WORD
        LocalVar   fpLdrBufSrc,WORD
        LocalVar   fTK_FF_BUF,BYTE
        LocalVar   fSEC_HLP,BYTE                                      ;@SEC

        ; BUGBUG - uses a LOT of stack that we can not afford to use.
        LocalVar  ldrbuf,PMPATHLEN        ; temp buffer for transpath etc.
        LocalVar  dummy,WORD              ; KLUDGE: see gshare.asm

        EnterProc

        push    edi                     ; save C register variables
        push    esi
        push    ebx

        mov     fTK_FF_BUF,0
ifdef SECURITY
        mov     fSEC_HLP,0                              ;@SEC
        mov     ebx,[_pTCBCur]
        test    [ebx].TCBSecFlags,TCBSEC_NOCALLOUT      ;@SEC From Security?
        jz      iosonosec                               ;@SEC
        mov     fSEC_HLP,1                              ;@SEC
iosonosec:                                              ;@SEC
endif

        mov     ebx,[_pTCBCur]
        test    [ebx].TCBForce_Flg,FF_BUF     ; buffer assigned?
        jz      short iosftopen1
        and     [ebx].TCBForce_Flg,not FF_BUF ; make like one isn't assigned
        inc     fTK_FF_BUF

iosftopen1:

;       save TCB variables

        SSToDS  edi,tcbsavebuf
        CCALL32 ioSaveTCB

;       start setting up for the call

        mov     ebx,[_pTCBCur]
        lea     ax,dummycds
        mov     [ebx].TCBpTmpCDS.Offst,ax       ; Initialize TCBpTmpCDS

;       allocate an SFT

        mov     [ebx].TCBProc_ID,0      ; No owner for this SFT
        CALL16  SFNAlloc                ; (bx) = SFN, [es:di] = SFT

        ASSUME  ES:NOTHING
        jc      isoie1

        mov     esi,[pSFN]
        mov     ds:[esi],bx             ; store SFN in caller's variable

;       store call arguments

        movzx   edi,di
        mov     ecx,[FileMode]
        mov     dword ptr es:[edi].sf_fsi.sfi_mode,ecx  ; file mode
        mov     es:[edi].sf_flags,SF_NOJFN
        mov     esi,[_pTCBCur]
        mov     word ptr ds:[esi].TCBThisSFT.Offst,di
        mov     word ptr ds:[esi].TCBThisSFT.Segmt,es

;       canonicalize file name

;       Here we guard against pszFname pointing to ptda_pLdrBuf. Loader does
;       this as an optimization.  In this case we skip transpath.

        mov     fpLdrBufSrc,0
        mov     eax,pszFname
;       movzx   edx,SS:[TKOPTDA.ptda_pLdrBuf]
;       SSToDS  edx
;       int     3
        mov     edx,_ldrpFileNameBuf
        cmp     eax,edx
        jne     short ioso1

        CALL16  GetTempBuffer          ; es:di --> temp buffer
        movzx   edi,di
        mov     ax,es
        movzx   eax,ax
        mov     SelTemp,eax
        mov     fpLdrBufSrc,1
        mov     TempBufferOff,di

        mov     esi,_ldrpFileNameBuf

        mov     ecx,PMPATHLEN
        rep     movsb

        mov     si,TempBufferOff        ; SI = temp buffer offset
        jmp     short ioso2

;       Get an alias to pszFname

ioso1:  FlatContext  <es>,ax
        xor     eax,eax
        mov     SelTemp,eax
        SSToDS  eax,SelTemp             ; selector holder
        CCALL32 _SELLdrDesc,<pszFname,MAXPATHLEN,eax>
                                        ; SelTemp:0 is the 16:16 pointer
        or      eax,eax
        jnz     isoie

        xor     si,si
ioso2:  mov     ds,SelTemp              ; [ds:si] = buffer pointer

        mov     edi,pLocalBuf
        or      edi,edi
        jnz     short ioso20
        lea     di,ldrbuf
ioso20: push    ebp                         ; TransPathCnvPathChars destroys bp
        CALL16  TransPathCnvPathChars
        pop     ebp
        pushf

ifdef SECURITY
        ; @SEC If we were called from security, skip around so we don't
        ; @SEC wipe out the loader file name buffer.

        cmp     fSEC_HLP,0                                              ;@SEC
        jnz     short iososec                                           ;@SEC
endif

        ; copy result into the ldr file name buffer

        push    si
        push    ds
        push    es
        mov     si,ss
        mov     ds,si
        lea     si,ldrbuf
        movzx   esi,si
        FlatContext  <es>,di
        mov     edi,es:_ldr16pFileNameBuf
        ror     edi,16
        mov     es,di
        ror     edi,16
        movzx   edi,di
        mov     ecx,PMPATHLEN
        repe    movsb
        pop     es
        pop     ds
        pop     si

iososec:
        cmp     fpLdrBufSrc,0
        je      short ioso3

        mov     es,SelTemp              ; [ds:si] = buffer pointer
        mov     di,TempBufferOff
        SaveReg <eax>
        CALL16  FreeTempBuffer
        RestoreReg <eax>
        jmp     short ioso4

ioso3:  SaveReg <eax>
        FlatContext <ds,es>,eax
        CCALL32 _SELFreeGDT,<SelTemp>   ; Free selector
        RestoreReg <eax>

ioso4:  popf
;       jc      isoie1            ; Error from trans path ;; #72625
        jc      isoie2            ; Error from trans path ;; #72625

;       set up more of the innumerable arguments to open

        FlatContext ds
        mov     ebx,_pTCBCur
                                        ;72417 moved from PTDA to TCB
        mov     [ebx].TCBSattrib,attr_hidden+attr_system+attr_directory
                                        ;72417 end
        TaskContext     ds,eax
        lea     ebx,[OpenArgFrame]
        xor     eax,eax
        mov     ds:[ebx].opn3s_EABufPtr,eax
        mov     ds:[ebx].opn3s_FileHandleLockIDPtr,eax
        mov     ecx,[FileMode]
        mov     dword ptr ds:[ebx].opn3s_Mode,ecx
        mov     ecx,[OpenFlag]
        mov     ds:[ebx].opn3s_Flag,cx
        mov     ds:[ebx].opn3s_Attrs,ax
        mov     ds:[ebx].opn3s_Size,eax
        mov     ds:[ebx].opn3s_ActionPtr,eax
        mov     ds:[ebx].opn3s_HandlePtr,eax
        mov     ds:[ebx].opn3s_NamePtr,eax

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

        CALL16  FSD_OpenCreate                  ; [ss:bx] = arg frame
        pushf
        CALL16  RlseBuffr
        popf
        jc      short isoie2                    ; open failed

        ASSUME  DS:NOTHING, ES:NOTHING
        FlatContext ds,bx

        xor     eax,eax
        mov     edi,[_pTCBCur]
        les     si,[edi].TCBThisSFT
        mov     es:[si].sf_ref_count,1  ; indicate one reference to SFT

isox1:  FlatContext es,bx
        movzx   eax,ax
        SSToDS  esi,tcbsavebuf
        CCALL32 ioRestoreTCB

        cmp     fTK_FF_BUF,0
        je      short noiosftres1
        mov     esi,[_pTCBCur]
        or      [esi].TCBForce_Flg,FF_BUF ; restore the flag

noiosftres1:

        pop     ebx                     ; restore C register variables
        pop     esi
        pop     edi

        LeaveProc
        RETC


isoie1: or      ax,ax         ; make sure we have a return code in ax
        jnz     isox1
        mov     ax, ERROR_NOT_ENOUGH_MEMORY
        jmp     short isox1


isoie2: FlatContext <ds,es>,edi
        push    ax

        mov     edi,[_pTCBCur]
        les     di,[edi].TCBThisSFT
        ASSUME  ES:NOTHING
        CALL16  SFLinkFree
        mov     bx,ds
        mov     es,bx
        ASSUME  ES:FLAT

        pop     ax
        or      ax,ax
        jnz     short isox1
        mov     ax, ERROR_FILE_NOT_FOUND
        jmp     short isox1

isoie:  Panic   <'_IOSftOpen: SELLdrDesc'>

EndProc _IOSftOpen


;***EP  _IOSftReadAt    - Read from a file at a given location
;***EP  _IOSftWriteAt   - Write to a file at a given location
;
;       ENTRY   [esp]    ret addr
;               [esp+4]  SFN, zero extended to a dword
;               [esp+08] pointer to count of bytes to read
;               [esp+12] 0:32 transfer address
;               [esp+16] 16:16 transfer address
;               [esp+20] file offset to read from
;
;       EXIT    eax = error code
;               transfer count pointer updated
; Reads are broken up into blocks of size 63.5K
CBREADBREAKUP     EQU   ((63 * 1024) + 512)

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

        ArgVar  uSFN,DWORD
        ArgVar  pcBytes,DWORD
        ArgVar  pXferAddr,DWORD
        ArgVar  psXferAddr,DWORD
        ArgVar  uOffset,DWORD

        LocalVar tcbsavebuf,TCBIOCopySize
        LocalVar SelTemp,DWORD          ; 16:16 Alias to the read buffer
        LocalVar IORoutine,DWORD        ; routine to do IO                ;@SEC
        LocalVar fTK_FF_BUF,BYTE
        LocalVar fSFLocked,BYTE         ; Flag to know whether SFT locked

        mov     eax, offset FLAT:IO_Read                                  ;@SEC
        jmp     short   IORW1                                             ;@SEC

Entry   _IOSftWriteAt                                                     ;@SEC
        mov     eax, offset FLAT:IO_Write                                 ;@SEC
IORW1:                                                                    ;@SEC
        EnterProc
        push    edi
        push    esi
        push    ebx

        mov     IORoutine,eax           ; Save IO routine address         ;@SEC

        xor     ebx,ebx
        mov     fSFLocked,bl            ; initialise flag for SFT locking
        mov     SelTemp,ebx             ; Allocate a new selector
        mov     fTK_FF_BUF,bl

        mov     esi,[_pTCBCur]
        test    [esi].TCBForce_Flg,FF_BUF     ; buffer assigned?
        jz      short iosftread1
        and     [esi].TCBForce_Flg,not FF_BUF ; make like one isn't assigned
        inc     fTK_FF_BUF

iosftread1:
        ; save TCB variables
        SSToDS  edi,tcbsavebuf
        CCALL32 ioSaveTCB

        ; Use the input parameter SFN to find the SFT
        mov     ebx,[uSFN]
        CALL16  SFFromSFN               ; pointer to the SFT returned in [es:di]
        ASSUME  ES:NOTHING
        mov     eax,ERROR_INVALID_HANDLE ; has the SFT gone away ?
        jc      israx

        ; save the SFT pointer
        mov     esi,[_pTCBCur]
        mov     word ptr [esi].TCBThisSFT.Offst,di
        mov     word ptr [esi].TCBThisSFT.Segmt,es
        mov     [esi].TCBfIOLock,0

        ; Serialise access to the SFT - the seek address is stored in the SFT
        CALL16  SFLock                   ; SFT pointer is already in es:di
        mov     eax,ERROR_INVALID_HANDLE ; did the SFT vanish ?
        jc      israx
        inc     fSFLocked                ; remember we locked the SFT

        ; do we need to seek, or are we at the correct offset already ?
        mov     eax,[uOffset]
        cmp     eax,es:[di].sf_fsi.sfi_position
        je      short isra20

        ; See if the user wants to seek                                   ;@SEC
        cmp     eax,0ffffffffh                                            ;@SEC
        je      short isra20                                              ;@SEC

        ; we need to seek, so do it
        mov     edx,eax                 ; eax already contains file offset
        ror     edx,16                  ; dx:ax = offset to seek to
        mov     cx,dx
        mov     si,ax                   ; cx:si = also offset to seek to
        xor     bx,bx                   ; seek type = 0 = absolute
        CALL16  FSD_ChgFilePtr
        ASSUME  DS:NOTHING, ES:NOTHING
        movzx   eax,ax
        jc      israx                   ; returned carry set on error,
                                        ; error code is in ax
isra20:
;       Lock the xfer area
;       perform the read
;       If read > CBREADBREAKUP, split reads into CBREADBREAKUP chunks

        FlatContext <ds,es>,ecx
        mov     eax,[pcBytes]
        xor     ebx,ebx
        xchg    ebx,[eax]               ; (EBX) = Xfer count
isra30: mov     ecx,ebx                 ; (ECX) = Xfer count
        cmp     ecx,CBREADBREAKUP
        jbe     short isra40
        mov     ecx,CBREADBREAKUP
isra40: sub     ebx,ecx                 ; (EBX) = residual count
                                        ; (ECX) = count of current read
;       Get a 16:16 alias to the read buffer

        SaveReg <ebx,ecx>               ; Save count and residual count
        cmp     [psXferAddr],0          ; did we get a 16:16 address
        je      short isra41            ;  no, make one
        mov     eax,psXferAddr
        add     [psXferAddr],ecx        ; Update to next Xfer Addr
        add     [pXferAddr],ecx         ; always update this Xfer addr
        jmp     short isra42

isra41: SSToDS  eax,SelTemp
        PushP   eax                     ; psel, for _SELLdrDesc
        PushP   ecx                     ; cb, for _SELLdrDesc
        PushP   [pXferAddr]             ; laddr, for _SELLdrDesc
        add     [pXferAddr],ecx         ; Update next Xfer Addr
        CCALL32 _SELLdrDesc,,,PushP
        or      eax,eax
        .errnz  NO_ERROR
        jnz     short isra90            ; SELLdrDesc failed
        mov     eax,SelTemp
        rol     eax,16                  ; EAX = 16:16 address to buffer

isra42: mov     esi,[_pTCBCur]
        mov     [esi].TCBDMAAdd,eax
        mov     ecx,[esp]               ; (ECX) = transfer count
        TaskContext ds,ebx              ; FSD_XXXX requires ds = TASKAREA  @SEC
        call    [IORoutine]                                               ;@SEC
        RestoreReg <edx,ebx>
                                        ; (EDX) = # of bytes to be read
                                        ; (EBX) = # of residual bytes
        movzx   ecx,cx                  ; (ECX) = actual bytes read/written
        FlatContext <ds,es>,esi
        jc      short isra60            ; don't forget to unlock!
        mov     esi,[pcBytes]
        add     [esi],ecx               ; update count read/written
        cmp     ecx,edx                 ; Did we read/write correctly
        jne     short isra50            ; No, abort now
        or      ebx,ebx                 ; Are we done ?
        jnz     isra30

isra50: xor     eax,eax                 ; Done, success
        .errnz  NO_ERROR

;       Get rid of 16-bit alias selector if needed

isra60: cmp     [psXferAddr],0          ; was a selector allocated
        jne     short isra90            ;  no
        mov     ebx,eax                 ; save error code in ebx
        CCALL32 _SELFreeGDT <SelTemp>   ; free the alias
        mov     eax,ebx                 ; restore error code
        jmp     short isra90

;       Unlock the area

israx:  movzx   eax,ax                  ; extend error code
        FlatContext <ds,es>,ebx         ; Restore FLAT Context

isra90:

        ; if we locked the SFT, free it
        cmp     fSFLocked,0
        jz      short isra91
        push    eax                     ; save the error code
        push    es                      ; save working regs
        push    edi
        mov     edi,_pTCBCur            ; get pointer to SFT entry in TCB
        les     di,[edi].TCBThisSFT
        CALL16  SFUnlock                ; Unlock the SFT - pointer in es:di
        pop     edi                     ; retore regs saved
        pop     es
        pop     eax                     ; restore the error code
isra91:

        SSToDS  esi,tcbsavebuf
        CCALL32 ioRestoreTCB            ; restore TCB variables

        cmp     fTK_FF_BUF,0            ; b724126
        je      short noioreadres
        mov     esi,[_pTCBCur]
        or      [esi].TCBForce_Flg,FF_BUF ; restore the flag

noioreadres:

        pop     ebx                     ; restore C register variables
        pop     esi
        pop     edi
        LeaveProc
        RETC
EndProc _IOSftReadAt

;***LP  IO_Read  -- thunk to FSD_Read                                     ;@SEC
;***LP  IO_Write -- thunk to FSD_Write                                    ;@SEC
;                                                                         ;@SEC
Procedure IO_Read                                                         ;@SEC
        CALL16  FSD_Read                                                  ;@SEC
        ret                                                               ;@SEC
EndProc IO_Read                                                           ;@SEC
                                                                          ;@SEC
Procedure IO_Write                                                        ;@SEC
        CALL16  FSD_Write_NT                                              ;@SEC
        ret                                                               ;@SEC
EndProc IO_Write                                                          ;@SEC



;***EP  _IOSftClose     - Close a file
;
;       _IOSftClose closes a file opened by _IOSftOpen
;
;       ENTRY   [esp]   ret addr
;               [esp+4] SFN, zero extended to a dword
;
;       EXIT    eax = error code
;
Procedure _IOSftClose
        ASSUME  DS:FLAT, ES:FLAT, FS:NOTHING, GS:NOTHING, SS:NOTHING

        ArgVar  uSFN,DWORD
        LocalVar tcbsavebuf,TCBIOCopySize
        LocalVar fTK_FF_BUF,BYTE

        EnterProc
        push    edi
        push    esi
        push    ebx

        mov     fTK_FF_BUF,0
                                        ; b724126
        mov     ebx,[_pTCBCur]
        test    [ebx].TCBForce_Flg,FF_BUF     ; buffer assigned?
        jz      short iosftcls1
        and     [ebx].TCBForce_Flg,not FF_BUF ; make like one isn't assigned
        inc     fTK_FF_BUF

; save the TCB variables
iosftcls1:
        SSToDS  edi,tcbsavebuf
        CCALL32 ioSaveTCB

        mov     ebx,[uSFN]
        CALL16  SFFromSFN               ; [es:di] = SFT on return
        ASSUME  ES:NOTHING
        mov     eax,ERROR_INVALID_HANDLE ; has the SFT gone away ?
        jc      short iscx

        mov     ebx,[_pTCBCur]
        mov     word ptr ds:[ebx].TCBThisSFT.Offst,di
        mov     word ptr ds:[ebx].TCBThisSFT.Segmt,es
        CALL16  FSD_Close               ; close the file; returns error in ax
        movzx   eax,ax
        jc      short iscx
        CALL16  SFLinkFree              ; free the SFT
        xor     eax,eax                 ; don't care if SFLinkFree failed

iscx:   FlatContext <ds,es>,edi
        SSToDS  esi,tcbsavebuf
        CCALL32 ioRestoreTCB

        cmp     fTK_FF_BUF,0              ; b724126
        je      short noioclsres
        mov     esi,[_pTCBCur]
        or      [esi].TCBForce_Flg,FF_BUF ; restore the flag

noioclsres:
        pop     ebx
        pop     esi
        pop     edi
        LeaveProc
        RETC
EndProc _IOSftClose




;***LP  _IOSftTransPath - Call TransPath
;
;       _IOSftTransPath provides an interface to the file
;       system from the loader to call TransPathCnvPathChars.
;
;       The result is always stored at pPTDACur->ptda_pLdrBuf
;
;       _IOSftTransPath will internal error if isIFS is set,
;       as no file system exists yet.
;
;       _IOSftTransPath (pchName);
;
;       ENTRY
;               pchName         : ASCIIZ filename to canonicalize
;
;       EXIT
;               The Return Value is held in EAX on exit
;
;               Return Value == NO_ERROR
;                       TransPathCnvPathChars was successful
;
;                   Side Effects :
;                       [WFP_Start]    -> beginning of buffer
;                       [WFP_Path_End] -> end of path part of target
;                       [Curr_Dir_End] -> end of curdir in path
;                       [TCBThishVPB]   = current hVPB
;                       [TCBThisFSC]   -> FSC
;                       [ptda_pLdrBuf] -> canonicalized filename
;
;               Return Value != NO_ERROR
;                       (EAX) = Error Code
;
;       USES            EAX, ECX, EDX, EFlags
;
;       Pseudocode :
;
;       Craft 16:16 alias to pchName
;
;       TransPathCnvPathChars
;
;       Eliminate 16:16 alias selector

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

        ArgVar  pchName,DWORD

        LocalVar        dummycds,<SIZE curdir>
        LocalVar        SelTemp,DWORD

        ; bugbug - nasty waste of stack space

        LocalVar  ldrbuf,PMPATHLEN        ; temp buffer for transpath etc.
        LocalVar  dummy,WORD              ; KLUDGE: see gshare.asm

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

;       We need a 16-bit alias to pchBuf

        mov     eax,_pTCBCur
        lea     bx,dummycds
        mov     [eax].TCBpTmpCDS.Offst,bx       ; Initialize TCBpTmpCDS

        xor     eax,eax
        mov     SelTemp,eax                     ; Allocate a new selector
        SSToDS  eax,SelTemp
        CCALL32 _SELLdrDesc <pchName,MAXPATHLEN,eax>; get SelTemp
        or      eax,eax
        .errnz  NO_ERROR
        jz      short tran1                     ; NO_ERROR from _SELLdrDesc

        Panic   <'_IOSftTransPath : _SELLdrDesc'>

;       16-bit alias selector to pchName exists in SelTemp

tran1:  mov     ds,SelTemp                      ; (DS:SI) source buffer
        xor     esi,esi

        lea     di,ldrbuf

        push    ebp
        CALL16  TransPathCnvPathChars
        pop     ebp

        pushf

        ; copy result to the ldr file name buffer

        push    si
        push    ds
        push    es
        mov     si,ss
        mov     ds,si
        lea     si,ldrbuf
        movzx   esi,si
        FlatContext  <es>,di
        mov     edi,es:_ldr16pFileNameBuf
        ror     edi,16
        mov     es,di
        ror     edi,16
        movzx   edi,di
        mov     ecx,PMPATHLEN
        repe    movsb
        pop     es
        pop     ds
        pop     si
        popf

        jc      short tran8

        xor     eax,eax                         ; assure NO_ERROR return code

;       Get rid of 16-bit alias selector
;       (EAX) = Error Code, if any

tran8:  FlatContext <ds,es>,edx                 ; (DS) = (ES) = Flat
        mov     ebx,eax                         ; EBX = error code
        CCALL32 _SELFreeGDT <SelTemp>           ; free the alias
        mov     eax,ebx                         ; EAX = error code

;       All done.  (EAX) = Error Code, if any

        RestoreReg      <es,ds,edi,esi,ebx>
        movzx   eax,ax                          ; Zero out high word
        LeaveProc
        RETC

EndProc _IOSftTransPath




;***LP  ioSaveTCB       - save TCB variables used by FAT file system
;
;       Because the FAT file system stores some of its local variables
;       in the TCB instead of on the stack, we have to save them away
;       before starting reentrant file system operations.
;
;       ENTRY   edi = flat addr of save buffer
;               ds,es = flat selector
;
;       EXIT    none
;
;       USES    edi,esi,ecx

Procedure ioSaveTCB,<near,far32>
        ASSUME  DS:FLAT, ES:FLAT, FS:NOTHING, GS:NOTHING, SS:NOTHING

        mov     esi,[_pTCBCur]
        lea     esi,[esi].TCBIOCopyStart
        mov     ecx,TCBIOCopySizeX SHR 2   ;#71331 New Size Variable
        rep movsd
        mov     esi,[_pTCBCur]             ;#71331 Must pick up the tmpnamebufl
        lea     esi,[esi].TCB_TmpNameBufL  ;#71331 as well to save.
        movsw                              ;#71331
        RETC
EndProc ioSaveTCB




;***LP  ioRestoreTCB    - restore TCB variables used by FAT file system
;
;       Because the FAT file system stores some of its local variables
;       in the TCB instead of on the stack, we have to save them away
;       before starting reentrant file system operations.
;
;       ENTRY   esi     = flat addr of save buffer
;               ds,es   = flat selector
;
;       EXIT    none
;
;       USES    edi,esi,ecx

Procedure ioRestoreTCB,<near,far32>
        ASSUME  DS:FLAT, ES:FLAT, FS:NOTHING, GS:NOTHING, SS:NOTHING

        mov     edi,[_pTCBCur]
        lea     edi,[edi].TCBIOCopyStart
        mov     ecx,TCBIOCopySizeX SHR 2   ;#71331 New Size Variable
        rep movsd
        mov     edi,[_pTCBCur]             ;#71331 Must pick up the tmpnamebufl
        lea     edi,[edi].TCB_TmpNameBufL  ;#71331 as well to save.
        movsw                              ;#71331
        RETC
EndProc ioRestoreTCB




;***EP  _SftFileSize - return the size for an open file
;
;       Use the passed SFN to find the a file's sft.  Get and return the
;       file's size in the sft.
;
;       ENTRY   [esp]   ret addr
;               [esp+4] SFN, zero extended to a dword
;               [esp+8] pointer to file size save location
;
;       EXIT    eax = error code
;

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

        ArgVar  uSFN,DWORD
        ArgVar  pFileSize,DWORD

        LocalVar tcbsavebuf,TCBIOCopySize
        LocalVar fTK_FF_BUF,BYTE

        EnterProc
        push    edi
        push    esi
        push    ebx

        mov     fTK_FF_BUF,0

        mov     esi,[_pTCBCur]
        test    [esi].TCBForce_Flg,FF_BUF     ; buffer assigned?
        jz      short iosftfile1
        and     [esi].TCBForce_Flg,not FF_BUF ; make like one isn't assigned
        inc     fTK_FF_BUF

; save the TCB variables
iosftfile1:
        SSToDS  edi,tcbsavebuf
        CCALL32 ioSaveTCB

        mov     ebx,[uSFN]
        movzx   ebx,bx                  ; 16 bit SFN
        CALL16  SFFromSFN               ; [es:di] = SFT
        ASSUME  ES:NOTHING
        mov     eax,ERROR_INVALID_HANDLE
        jc      short sfsx

        ; Save the file size
        mov     ebx,dword ptr es:[di].sf_fsi.sfi_size
        mov     esi,[pFileSize]
        mov     [esi],ebx
        xor     eax,eax

sfsx:   FlatContext es,edi
        SSToDS  esi,tcbsavebuf
        CCALL32 ioRestoreTCB

        cmp     fTK_FF_BUF,0
        je      short noiosftfil
        mov     esi,[_pTCBCur]
        or      [esi].TCBForce_Flg,FF_BUF ; restore the flag

noiosftfil:

        pop     ebx
        pop     esi
        pop     edi
        LeaveProc
        RETC
EndProc _SftFileSize




;***LP  Canon - w_Canon called from 32-bit C.
;
;       _Canon calls w_canon. Note that the procedure expects selectors
;       and offsets, not addresses.
;
;       ENTRY   NameSel         - Source filename selector
;               NameOff         - Source filename offset
;               BackLim         - See w_canon
;               BufEnd          - See w_canon
;               Flags           - See w_canon
;
;       EXIT    Success         - NO_ERROR
;               Failure         - See w_Canon
;

Procedure _Canon,near

ArgVar  NameSel,DWORD
ArgVar  NameOff,DWORD
ArgVar  BackLim,DWORD
ArgVar  BufEnd,DWORD
ArgVar  Flags,DWORD

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

        mov     esi,NameOff             ; Only lower 16-bits count.
        movzx   esi,si
        mov     edi,esi                 ; source = destination
        mov     ebx,BackLim             ; (EBX) = buffer limit
        mov     edx,Flags               ; (EDX) = flags
        mov     eax,BufEnd              ; (EAX) = buffer end
        mov     es,NameSel              ; (ES:EDI) = destination
        mov     ds,NameSel              ; (DS:ESI) = source

        CALL16  w_Canon                 ; Call 16-bit routine

        FlatContext
        jc      short can1              ; ERROR!
        xor     eax,eax                 ; NO_ERROR
        jmp     short can2

can1:   mov     eax,ERROR_INVALID_NAME

can2:   RestoreReg <edi,esi,ebx,es,ds>
        LeaveProc

        RETC
EndProc _Canon




HIGH32CODE ENDS

        END
