;
; Utilities called by C programs in filesys:
;
;       strlenfc
;       strcmpfc
;       strncmpfc
;       strcpyfc
;       memsetfc
;       (the above procedures adopted from lanman group's netlib, which
;       in turn was adtoped from language group's C runtime lib)

        .286p
        .xlist
;include basemaca.inc
;include osmaca.inc
;include mi.inc
;include vmowner.inc
;include seldesc.inc
;include virtsym.inc

include fnofs.inc
include dosseg.inc
include basemaca.inc
include osmaca.inc
include osconst.inc
include oldmaca.inc
include mi.inc
include defdbug.inc
include dossymc.inc
include chardd.inc
include curdir.inc
include dbcs.inc
include devhdr.inc
include error.inc
include meta.inc
include vmowner.inc
include virtsym.inc
include seldesc.inc
include proc.inc
include pgexport.inc
include tkexport.inc
        .list


           ReferGlobal _UdelSem
           ReferTask   CurrTCB,WORD

           EXTRNFAR w_Read
           EXTRNFAR api_Close
           EXTRNFAR w_Write
           EXTRNFAR w_LSeek
           EXTRNFAR api_OpenCreate
           EXTRNFAR w_FindFirst
           EXTRNFAR w_Current_Dir
           EXTRNFAR w_QCurDisk
           EXTRNFAR w_Rename
           EXTRNFAR w_MkDir
           EXTRNFAR w_Unlink
           EXTRNFAR w_NewSize
           EXTRNFAR w_ChMod
           EXTRNFAR w_QPathInfo
           EXTRNFAR w_GetDateTime
           EXTRNFAR w_FindClose
           EXTRNFAR SegFree
           EXTRNFAR SegAlloc
           EXTRNFAR w_qFSAttach

;           EXTRN32  _KSEMInit
           EXTRN32  _KSEMRequestMutex
           EXTRN32  _KSEMReleaseMutex


DATA  SEGMENT WORD PUBLIC 'LOWDATA'
DATA  ENDS

CONSTANTS SEGMENT WORD PUBLIC 'LOWDATA'
CONSTANTS ENDS

TABLE SEGMENT WORD PUBLIC 'LOWDATA'
TABLE ENDS

DOSGROUP  GROUP  DATA, CONSTANTS, TABLE

          FARCODE HIGH3
HIGH3CODE SEGMENT
          ASSUME  DS: DOSGROUP, SS: TASKAREA

;***    unsigned int strlenf(char far *pstr)
;
;       Returns number of bytes in a null-terminated string. The null does
;       not count.
;
;       DEF:    unsigned int strlenf(char far *pstr)
;
;       ENTRY:  pstr = far (long) pointer to string
;
;       EXIT:   returns length of string

Procedure _strlenfc, NEAR

ArgVar slf_pstr,DWORD           ; pointer to string

        EnterProc
        mov     dx,di           ; Preserve DI
        les     di,slf_pstr     ; ES:DI -> string
        xor     ax,ax           ; null byte
        mov     cx,-1
        repne   scasb           ; scan for null, CX = -(1+strlen(str))
        not     cx
        dec     cx
        xchg    ax,cx           ; AX = strlen(str)
        mov     di,dx           ; Restore DI
        LeaveProc
        ret

EndProc _strlenfc


;***    int strcmp(char far *pstr1, char far *pstr2)
;
;       Compares two strings.
;
;       ENTER   pstr1 -> first string
;               pstr2 -> second string
;
;       EXIT    if both strings are ASCII strings then
;                 returns -1 if first string < second string
;                          0 if strings are equal
;                          1 if first string > second string
;               if either string contains DBCS then
;                 returns  0      if strings are equal
;                         -1 or 1 if strings are not equal

Procedure _strcmpfc, NEAR

ArgVar scf_pstr1,DWORD
ArgVar scf_pstr2,DWORD

        EnterProc
        mov     dx,di           ; preserve SI and DI
        mov     bx,si
        push    ds              ; preserve DS
        lds     si,scf_pstr1    ; ds:si -> str1
        les     di,scf_pstr2    ; es:di -> str2
        xor     ax,ax
        mov     cx,-1
        repne   scasb           ; compute length of str2
        not     cx              ; CX = strlen(str2)+1

        sub     di,cx           ; restore ES:DI -> str2
        repe    cmpsb           ; compare while equal, at most length of str2
        je      sc10            ; str2 == str1?  (AX = 0)
                                ;       str2 < str1     str2 > str1
        sbb     ax,ax           ;       AX=-1, CY=1     AX=0, CY=0
        sbb     ax,-1           ;       AX=-1           AX=1

sc10:   pop     ds              ; restore DS
        mov     si,bx           ; restore SI and DI
        mov     di,dx
        LeaveProc
        ret

EndProc _strcmpfc


;***    int strncmpf(char far *pstr1, char far *pstr2, unsigned int count)
;
;       Compares two strings (similar to strcmp), but examines at most
;       count bytes. The effect is like truncating both strings to count
;       bytes long and then do strcmpf.
;
;       ENTER   pstr1 -> first string
;               pstr2 -> second string
;               count  = maximum number of bytes to examine
;
;       EXIT    if both strings are ASCII strings then
;                 returns -1 if first string < second string
;                          0 if strings are equal
;                          1 if first string > second string
;               if either string contains DBCS then
;                 returns  0      if strings are equal
;                         -1 or 1 if strings are not equal

Procedure _strncmpfc, NEAR


ArgVar snc_pstr1,DWORD
ArgVar snc_pstr2,DWORD
ArgVar snc_count,WORD

        EnterProc
        SaveReg <di,si,ds>

        mov     cx,snc_count    ; cx = max number of bytes to compare
        jcxz    snc20           ; it's as if strings are equal

        mov     bx,cx           ; bx saves count
        les     di,snc_pstr1    ; es:di -> str1

        mov     si,di           ; si saves first pointer
        xor     ax,ax           ; ax=0
        repne   scasb           ; count bytes
        neg     cx              ; cx=count - strlen
        add     cx,bx           ; strlen + count - strlen

        mov     di,si           ; restore first pointer

        lds     si,snc_pstr2    ; ds:si -> str2

        repe    cmpsb           ; compare strings
        mov     al,[si-1]
        xor     cx,cx

        cmp     al,es:[di-1]    ; last-first
        ja      snc10
        je      snc20

        dec     cx              ; first string is bigger
        dec     cx              ; make FFFE so 'not' will give 0001

snc10:  not     cx              ; return -1

snc20:  mov     ax,cx           ; return value

        RestoreReg <ds,si,di>
        LeaveProc
        ret
EndProc _strncmpfc



;*** unsigned long int ulongmul (unsigned long int ulong_1, unsigned long int ulong_2)
;
;       Multiplies two unsigned long integers.
;
;       ENTER   ulong_1 -> first unsigned long integer
;               ulong_2 -> second unsigned long integer
;
;       EXIT    returns (unsigned long) (ulong_1 * ulong_2)
;

Procedure _ulongmulc, NEAR

ArgVar ulong_1,DWORD
ArgVar ulong_2,DWORD

        EnterProc
        SaveReg <cx,di,si,ds>

        mov    ax, word ptr ulong_2+2   ;hi2
        mov    cx, word ptr ulong_1     ;lo1
        mul    cx                       ;lo1 * hi2
        mov    si, ax

        mov    ax, word ptr ulong_2     ;lo2
        mov    cx, word ptr ulong_1+2   ;hi1
        mul    cx                       ;hi1 * lo2
        mov    di, ax

        mov    ax, word ptr ulong_2     ;lo2
        mov    cx, word ptr ulong_1     ;lo1
        mul    cx                       ;lo1 * lo2

        add   dx, si
        adc   dx, di

        RestoreReg <ds,si,di,cx>
        LeaveProc
        ret

EndProc _ulongmulc



;*** unsigned long int ushortmul (unsigned int ushort_1, unsigned int ushort_2)
;
;       Multiplies two unsigned short integers.
;
;       ENTER   ushort_1 -> first unsigned short integer
;               ushort_2 -> second unsigned short integer
;
;       EXIT    returns (unsigned long) (ushort_1 * ushort_2)
;

Procedure _ushortmulc, NEAR

ArgVar ushort_1,WORD
ArgVar ushort_2,WORD

        EnterProc
        SaveReg <cx,ds>

        mov ax, ushort_1
        mov cx, ushort_2
        mul cx

        RestoreReg <ds,cx>
        LeaveProc
        ret

EndProc _ushortmulc


;*** unsigned udiv (unsigned long int Numerator, unsigned int Denominator)
;
;       Divides an unsigned long integer by an unsigned short
;       integer.
;
;       ENTER   Numerator   ->  unsigned long NUMR operand
;               Denominator ->  unsigned short DIVR operand
;
;       EXIT    returns (unsigned) (Numerator / Denominator)
;               Note: remainder is not returned
;

Procedure _udivc, NEAR

ArgVar Numerator,DWORD
ArgVar Denominator,WORD

        EnterProc
        SaveReg <cx,ds>

        mov ax, word ptr Numerator
        mov dx, word ptr Numerator+2
        mov cx, Denominator
        div cx
        xor dx, dx

        RestoreReg <ds,cx>
        LeaveProc
        ret

EndProc _udivc

;***    char far *strcpyf(char far *pDest, char far *pSrc)
;
;       Copies source string to destination.
;
;       ENTER   pDest -> points to destination
;               pSrc  -> points to source string
;
;       EXIT    returns pDest


Procedure _strcpyfc, NEAR

ArgVar scy_pDest,DWORD
ArgVar scy_pSrc,DWORD

        EnterProc
        mov     dx,di           ; Preserve SI and DI
        mov     bx,si
        push    ds              ; Preserve DS
        lds     si,scy_pSrc     ; ds:si -> Src
        mov     di,si           ; set ES:DI to DS:SI for first part
        mov     ax,ds
        mov     es,ax

        xor     ax,ax
        mov     cx,-1           ; find length of src
        repne   scasb
        not     cx              ; CX=strlen(src)+1

        les     di,scy_pDest    ; es:di -> Dest
        mov     ax,di           ; AX = return value (offset)
;
; There are 4 situations as far as word alignment of "src" and "dst":
;       1. src and dst are both even    (best case)
;       2. src is even and dst is odd
;       3. src is odd and dst is even
;       4. src and dst are both odd     (worst case)
;
; Case #4 is much faster if a single byte is copied before the
; REP MOVSW instruction.  Cases #2 and #3 are effectively unaffected
; by such an operation.  To maximum the speed of this operation,
; only DST is checked for alignment.  For cases #2 and #4, the first
; byte will be copied before the REP MOVSW.
;
        test    al,1            ; fast check for dst being odd address
        jz      scy10

        movsb                   ; move a byte to improve alignment
        dec     cx
;
; Now the bulk of the copy is done using REP MOVSW.  This is much
; faster than a REP MOVSB if the src and dst addresses are both
; word aligned and the processor has a 16-bit bus.  Depending on
; the initial alignment and the size of the region moved, there
; may be an extra byte left over to be moved.  This is handled
; by the REP MOVSB, which moves either 0 or 1 bytes.
;
scy10:  shr     cx,1            ; Shift CX for count of words
        rep     movsw           ; CF set if one byte left over
        adc     cx,cx           ; CX = 1 or 0, depending on Carry Flag
        rep     movsb           ; possible final byte
;
; Return the Dest address in DX:AX
;
        mov     si,bx
        mov     di,dx           ; Restore SI and DI

        pop     ds              ; restore ds
        mov     dx,es           ; segment part of dest address
        LeaveProc
        ret

EndProc _strcpyfc


;***    char far *memsetf(char far *pDest, char val, unsigned int count)
;
;       Fill count bytes in destination buffer with value val.
;
;       ENTER   pDest -> destination buffer
;               val    = fill value
;               count  = number of bytes to fill
;
;       EXIT    returns pDest


Procedure _memsetfc, NEAR

ArgVar msf_pDest,DWORD
ArgVar msf_val,DBYTE            ; C passes a char in a word
ArgVar msf_count,WORD

        EnterProc
        push    di

        les     di,msf_pDest    ; es:di -> dest

        mov     bx,di           ; bx saves dest pointer
        mov     cx,msf_count    ; cx = number of bytes to fill
        jcxz    msf20           ; if no work to do

        mov     al,msf_vall     ; al = fill value
        mov     ah,al           ;   put it in ah too
        mov     dx,di
        shr     dx,1            ; on word boundary?
        jnc     msf10           ;   yes, store by words
                                ;   no, do the leading (odd) byte first
        stosb
        dec     cx              ; 1 byte down, cx-1 to go

msf10:  mov     dx,cx           ; odd byte to move or not? dx remembers
        shr     cx,1            ; divide 2; we're moving words, not bytes

        rep     stosw

        shr     dx,1            ; see if an odd byte to move
        jnc     msf20

        mov     es:[di],al      ; store the odd byte

msf20:  mov     ax,bx           ; return value: dest addr

        mov     dx,es           ; segment part of addr
        pop     di
        LeaveProc
        ret

EndProc _memsetfc


Procedure _DOSFORCEDELETE , NEAR

ArgVar pszFName, DWORD
ArgVar ulReserved, DWORD

          EnterProc
          SaveReg <bx,cx,si,di>

          push word ptr pszFName+2
          pop  ds
          mov  dx, word ptr pszFName

          push bp
          CALLFAR w_Unlink                ; call the worker
          pop  bp

          jc   DFD_Done

          xor  ax, ax
DFD_Done:

          RestoreReg <di,si,cx,bx>
          LeaveProc
          ret

EndProc   _DOSFORCEDELETE


Procedure _DOSMKDIR , NEAR

ArgVar szDeleteDir, DWORD
ArgVar ulReserved, DWORD

          EnterProc
          SaveReg <bx,cx,si,di,es,ds>

          push word ptr szDeleteDir+2      ; segment of path string
          pop  ds                          ;
          mov  dx, word ptr szDeleteDir    ; offset of path string

          mov  si, 0
          mov  bx, 0                       ; SI:BX = NULL pointer (no EA)

          push bp
          CALLFAR w_MkDir                  ; call the worker
          pop  bp

          jc   DMD_Done

          xor  ax, ax
DMD_Done:
          RestoreReg <ds,es,di,si,cx,bx>
          LeaveProc
          ret

EndProc   _DOSMKDIR


Procedure _DOSMOVE , NEAR

ArgVar pszFName,DWORD
ArgVar pszTargetPath, DWORD
ArgVar ulReserved, DWORD

          EnterProc
          SaveReg <bx,cx,si,di,es,ds>

          push word ptr pszFName+2        ; segment of old name
          pop  ds                         ;
          mov  dx, word ptr pszFName      ; offset of old name

          push word ptr pszTargetPath+2   ; segment of new name
          pop  es                         ;
          mov  di, word ptr pszTargetPath ; offset of new name

          push bp
          CALLFAR w_Rename                ; call the worker
          pop  bp

          jc   DMV_Done
          xor  ax, ax
DMV_Done:

           RestoreReg <ds,es,di,si,cx,bx>
           LeaveProc
           ret

EndProc   _DOSMOVE


Procedure _DOSQCURDISK , NEAR

ArgVar pusCurDisk, DWORD
ArgVar pulDriveMap, DWORD

          EnterProc
          SaveReg <bx,cx,si,di,es,ds>

          push bp
          CALLFAR w_QCurDisk              ; call the worker
          pop  bp

          push word ptr pusCurDisk+2      ; segment of current disk var
          pop  es                         ;
          mov  di, word ptr pusCurDisk    ; offset of current disk var
          mov  es:[di], bx                ; store default drive

          push word ptr pulDriveMap+2     ; segment of logical map var
          pop  es                         ;
          mov  di, word ptr pulDriveMap   ; offset of logical map var
          mov  es:[di], ax                ; store default drive (low word)
          mov  es:[di+2], dx              ; store default drive (high word)

          RestoreReg <ds,es,di,si,cx,bx>
          LeaveProc
          ret

EndProc   _DOSQCURDISK


Procedure _DOSQCURDIR, NEAR

ArgVar    usCurDisk, WORD
ArgVar    pszSourcePath, DWORD
ArgVar    pusDirPathLen, WORD

          EnterProc
          SaveReg <bx,cx,si,di,es,ds>

          push word ptr pusDirPathLen+2
          pop  es
          mov  di, word ptr pusDirPathLen
          mov  cx, word ptr es:[di]     ; CX = buffer length

          mov  bx, word ptr pszSourcePath+2
          mov  si, word ptr pszSourcePath

          mov  dx, usCurDisk            ; drive number into dx

          push bp
          CALLFAR w_Current_Dir
          pop  bp
          jc   DQC_Done

          push word ptr pusDirPathLen+2
          pop  es
          mov  di, word ptr pusDirPathLen
          mov  word ptr es:[di], cx     ; save length of current directory

          xor  ax, ax
DQC_Done:

          RestoreReg <ds,es,di,si,cx,bx>
          LeaveProc
          ret

EndProc   _DOSQCURDIR


Procedure P_DOSFINDFIRST, NEAR

ArgVar    FFS_Reserved,       DWORD
ArgVar    FFS_SearchCountPtr, DWORD
ArgVar    FFS_RsltBufLen,     WORD
ArgVar    FFS_RsltBufPtr,     DWORD
ArgVar    FFS_Attribute,      WORD
ArgVar    FFS_HandlePtr,      DWORD
ArgVar    FFS_FileNamePtr,    DWORD

          EnterProc
          SaveReg <bx,cx,si,di,es,ds>

          mov  al, 1                          ; AL = interface level 1

          push word ptr FFS_FileNamePtr+2
          pop  ds
          mov  si, word ptr FFS_FileNamePtr ; DS:SI -> filename in kernel buffer

          xor  dx, dx                         ; 16 bit buffers

          lea  bx, FFS_Reserved               ; parameter packet on stack

          push bp
          CALLFAR w_FindFirst                    ; call the worker
          pop  bp
          jc   DFF_Done

          push word ptr FFS_HandlePtr+2
          pop  es
          mov  di, word ptr FFS_HandlePtr
          mov  word ptr es:[di], bx           ;Store search handle


          push word ptr FFS_SearchCountPtr+2
          pop  es
          mov  di, word ptr FFS_SearchCountPtr
          mov  word ptr es:[di], cx           ;Store search count

          xor  ax, ax
DFF_Done:
          RestoreReg <ds,es,di,si,cx,bx>
          LeaveProc
          ret 24
EndProc   P_DOSFINDFIRST


Procedure _DOSFINDCLOSE, NEAR

ArgVar    usHandle, WORD

          EnterProc
          SaveReg <bx,cx,si,di,es,ds>

          mov  bx, usHandle               ; get search handle

          push bp
          CALLFAR w_FindClose             ; call the worker
          pop  bp

          RestoreReg <ds,es,di,si,cx,bx>
          LeaveProc
          ret
EndProc   _DOSFINDCLOSE

Procedure _modify_fSharing, NEAR                                     ;d25363

ArgVar    SrvAttrib, WORD

          EnterProc

          mov   ax,[SrvAttrib]
          push  bp
          mov   bp,CurrTCB
          or    ah,ah
          jnz   short mfs10

          cmp   [bp].TCBfSharing, -1
          jnz   short mfsx

          mov   ah,0ffh
          mov   al,[bp].TCBSrvAttrib
          mov   [bp].TCBSrvAttrib, 0
          mov   [bp].TCBfSharing, 0
          jmp   short mfsx

mfs10:    mov   [bp].TCBSrvAttrib,al
          mov   [bp].TCBfSharing, -1

mfsx:     pop   bp

          LeaveProc
          ret

EndProc   _modify_fSharing


Procedure P_DOSOPEN, NEAR

ArgVar    ulReserved,      DWORD
ArgVar    usOpenMode,      WORD
ArgVar    usOpenFlag,      WORD
ArgVar    usFileAttribute, WORD
ArgVar    ulFileSize,      DWORD
ArgVar    pusAction,       DWORD
ArgVar    phControlFile,   DWORD
ArgVar    pszControlFile,  DWORD

          EnterProc
          SaveReg <bx,cx,si,di,es,ds>

          mov  al, 1                       ;interface level 1

          push word ptr pszControlFile+2   ;
          pop  ds                          ;
          mov  dx, word ptr pszControlFile ; address of file name

          lea  bx, ulReserved              ; parameter packet on stack

          push bp
          CALLFAR api_OpenCreate              ; call the worker (@PhysDisk)
          pop  bp
          jc  DOP_Done

          push word ptr phControlFile+2
          pop  es
          mov  di, word ptr phControlFile
          mov  word ptr es:[di], ax        ;store handle

          push word ptr pusAction+2
          pop  es
          mov  di, word ptr pusAction
          mov  word ptr es:[di], bx        ;store action taken

          xor  ax, ax

DOP_Done:
          RestoreReg <ds,es,di,si,cx,bx>
          LeaveProc
          ret 26

EndProc   P_DOSOPEN


Procedure _DOSCHGFILEPTR , NEAR

ArgVar    hControlFile, WORD
ArgVar    ulDistance, DWORD
ArgVar    usMoveType, WORD
ArgVar    pulFilePointer, DWORD

          EnterProc
          SaveReg <bx,cx,si,di,es,ds>

          mov  bx, hControlFile            ; file handle
          mov  ax, usMoveType              ; type of move
          mov  dx, word ptr ulDistance     ; lo word of distance
          mov  cx, word ptr ulDistance+2   ; hi word of distance

          xor     di,di                   ; fake low word of filehandlelockID
          xor     si,si                   ; fake high word of filehandlelockID
          push bp
          CALLFAR w_LSeek                     ; call worker
          pop  bp
          jc   DLS_Done

          push word ptr pulFilePointer+2     ;
          pop  es                          ;
          mov  bx, word ptr pulFilePointer ; get address of new position
          mov  es:[bx], ax                 ; store lo word of position
          mov  es:[bx+2], dx               ; store hi word of position

          xor  ax, ax                      ; clear error return
DLS_Done:
          RestoreReg <ds,es,di,si,cx,bx>
          LeaveProc
          ret
EndProc   _DOSCHGFILEPTR


Procedure _DOSPWRITE, NEAR

ArgVar    hControlFile, WORD
ArgVar    pDelFileInfo, DWORD
ArgVar    usSize, WORD
ArgVar    pusBytesWritten, DWORD

          EnterProc
          SaveReg <bx,cx,si,di,es,ds>

          mov  bx, hControlFile             ; file handle
          mov  cx, usSize                   ; number of bytes to write

          push word ptr pDelFileInfo+2      ;
          pop  ds                           ;
          mov  dx, word ptr pDelFileInfo    ; address of user buffer

          xor     si,si                   ; fake filehandlelockID lowword
          xor     di,di                   ; fake filehandlelockID highword
          push bp
          CALLFAR w_Write                   ; call worker
          pop  bp
          jc pdw_error

          push word ptr pusBytesWritten+2   ;
          pop  es                           ;
          mov  bx, word ptr pusBytesWritten ; get address of output variable
          mov  es:[bx], ax                  ; return number of bytes written

          xor  ax, ax                       ; clear error return

pdw_error:
          RestoreReg <ds,es,di,si,cx,bx>
          LeaveProc
          ret
EndProc   _DOSPWRITE


Procedure _DOSCLOSE, NEAR

ArgVar    hControlFile, WORD

          EnterProc
          SaveReg <bx,cx,dx,si,di,es,ds>

          xor cx,cx                         ; Clear lockid for close #57983
          xor dx,dx                         ; Clear lockid for close #57983

          mov bx, hControlFile              ; handle of control file

          push bp
          CALLFAR api_Close                 ; call the worker (@PhysDisk)
          pop  bp
          jc   DCL_Done

          xor  ax, ax                       ; clear error return

DCL_Done:
          RestoreReg <ds,es,di,si,dx,cx,bx>
          LeaveProc
          ret
EndProc   _DOSCLOSE


Procedure _DOSREAD, NEAR

ArgVar    hControlFile, WORD
ArgVar    pBufferRecord, DWORD
ArgVar    usSize, WORD
ArgVar    pusBytesWritten, DWORD

          EnterProc
          SaveReg <bx,cx,si,di,es,ds>

          mov  bx, hControlFile              ; handle

          mov  cx, usSize                    ; size of buffer

          push word ptr pBufferRecord+2
          pop  ds                            ; read buffer selector
          mov  dx, word ptr pBufferRecord    ; read buffer offset

          xor     si,si                      ; fake filehandlelockID lowword
          xor     di,di                      ; fake filehandlelockID highword
          push bp
          CALLFAR w_Read
          pop  bp
          jc   pdr_done                      ; exit now if error

          push word ptr pusBytesWritten+2    ;
          pop  es                            ; selector of bytes written var
          mov  bx, word ptr pusBytesWritten  ; offset of bytes written var
          mov  es:[bx], ax                   ; return bytes written

          xor  ax, ax                        ; return no error

pdr_done:
          RestoreReg <ds,es,di,si,cx,bx>
          LeaveProc
          ret
EndProc   _DOSREAD


Procedure _DOSNEWSIZE, NEAR

ArgVar    hControlFile, WORD
ArgVar    ulFilePointer, DWORD

          EnterProc
          SaveReg <bx,cx,si,di,es,ds>

          mov bx, hControlFile              ; file handle

          mov dx, word ptr ulFilePointer    ; lo word of new size
          mov cx, word ptr ulFilePointer+2  ; hi word of new size

          xor     si,si                   ; fake filehandlelockID lowword
          xor     di,di                   ; fake filehandlelockID highword
          push bp
          CALLFAR w_NewSize                 ; call the worker
          pop  bp
          jc   DNS_Done

          xor  ax, ax                       ; clear error return

DNS_Done:
          RestoreReg <ds,es,di,si,cx,bx>
          LeaveProc
          ret
EndProc   _DOSNEWSIZE


Procedure _DOSSETFILEMODE, NEAR

ArgVar    pszFileName, DWORD
ArgVar    usAttribute, WORD
ArgVar    ulReserved, DWORD

          EnterProc
          SaveReg <bx,cx,si,di,es,ds>

          mov  al, 1                         ; SET attributes

          mov  cx, usAttribute               ; attributes


          push word ptr pszFileName+2        ;
          pop  ds                            ; Filename segment
          mov  dx, word ptr pszFileName      ; Filename offset

          push bp
          CALLFAR w_ChMod                    ; call worker
          pop  bp
          jc   DSF_Done

          xor  ax, ax                        ; clear error return

DSF_Done:
          RestoreReg <ds,es,di,si,cx,bx>
          LeaveProc
          ret
EndProc   _DOSSETFILEMODE


Procedure _DOSQPATHINFO, NEAR

ArgVar    pszPathString,     DWORD
ArgVar    usPathInfoLevel,   WORD
ArgVar    pPathInfoBuf,      DWORD
ArgVar    usPathInfoBufSize, WORD
ArgVar    ulReserved,        DWORD

          EnterProc
          SaveReg <bx,cx,si,di,es,ds>

          mov  cx, usPathInfoBufSize

          mov  bx, usPathInfoLevel

          push word ptr pPathInfoBuf+2    ;
          pop  es                         ; Info buffer segment
          mov  di, word ptr pPathInfoBuf  ; Info buffer offset

          push word ptr pszPathString+2   ;
          pop  ds                         ; Path segment
          mov  dx, word ptr pszPathString ; Path offset

          push bp
          CALLFAR w_QPathInfo             ; call the worker
          pop  bp
          jc   DQI_Done

          xor  ax, ax                     ;clear error return
DQI_Done:
          RestoreReg <ds,es,di,si,cx,bx>
          LeaveProc
          ret

EndProc   _DOSQPATHINFO


Procedure _DOSGETDATETIME, NEAR

ArgVar    pDateTime, DWORD

          EnterProc
          SaveReg <bx,cx,si,di,es,ds>

          push word ptr pDateTime+2       ;
          pop  bx                         ; Date/Time structure segment
          mov  di, word ptr pDateTime     ; Date/Time structure offset

          push bp
          CALLFAR w_GetDateTime           ; call the worker
          pop  bp

          RestoreReg <ds,es,di,si,cx,bx>
          LeaveProc
          ret

EndProc   _DOSGETDATETIME


Procedure _DOSALLOCSEG, NEAR

ArgVar    usBytesNeeded,  WORD
ArgVar    pusReturnedSel, DWORD
ArgVar    usUnused,       WORD

          EnterProc
          SaveReg <bx,cx,si,di,es,ds>

          xor  ax, ax                      ;
          mov  bx, usBytesNeeded           ; ax:bx = size

          mov  ch, D_DATA0                 ;
          mov  cl, SA_GDT                  ;
          mov  si, HF_MOVABLE              ;
          mov  di, FSCDEVTMPOWNER          ;
          push bp
          CALLFAR SegAlloc                 ; bx:00 -> allocated segment
          pop  bp
          jc   DAS_Done                    ; SegAlloc failed?

          push word ptr pusReturnedSel+2   ;
          pop  es                          ; selector of seg variable
          mov  di, word ptr pusReturnedSel ; offset of seg variable
          mov  es:[di], bx                 ; return selector

          xor  ax, ax                      ; clear error return
DAS_Done:
          RestoreReg <ds,es,di,si,cx,bx>
          LeaveProc
          ret
EndProc   _DOSALLOCSEG


Procedure _DOSFREESEG, NEAR

ArgVar    usSelector, WORD

          EnterProc
          SaveReg <bx,cx,si,di,ds>

          mov  ax, usSelector
          mov  cx, 0
          push bp
          CALLFAR SegFree
          pop  bp

          RestoreReg <ds,di,si,cx,bx>
          LeaveProc
          ret
EndProc   _DOSFREESEG


Procedure P_DOSQFSATTACH, NEAR

ArgVar    ulUnused,       DWORD
ArgVar    DataBufferLen,  DWORD
ArgVar    DataBuffer,     DWORD
ArgVar    FSAInfoLevel,   WORD
ArgVar    Ordinal,        WORD
ArgVar    DeviceName,     DWORD


          EnterProc
          SaveReg <bx,cx,si,di,es,ds>

          mov  ax, FSAInfoLevel            ;

          push word ptr DeviceName+2       ;
          pop  ds                          ; selector of device name
          mov  si, word ptr DeviceName     ; offset of device name

          lea  bx, ulUnused                ; parameter packet on stack

          push bp
          CALLFAR w_qFSAttach              ;
          pop  bp
          jc   QFA_Done                    ; failed?

          xor  ax, ax                      ; clear error return

QFA_Done:
          RestoreReg <ds,es,di,si,cx,bx>
          LeaveProc
          ret
EndProc   P_DOSQFSATTACH



;Procedure _INITSEM, NEAR
;
;         EnterProc
;          SaveReg <bx,cx,si,di,es,ds>
;
;          .386P
;          CpuMode 386
;          FlatContext <DS, ES>,BX
;          CCALL32 _KSEMInit,<<offset FLAT:_UdelSem>, KRNL_MUTEXSEM, 0>
;          CpuMode Reset
;
;          RestoreReg <ds,es,di,si,cx,bx>
;         LeaveProc
;          ret
;EndProc   _INITSEM

Procedure _SEM_REQUEST, NEAR

          EnterProc
          SaveReg <bx,cx,si,di,es,ds>

          .386P
          CpuMode 386
          FlatContext <DS, ES>,BX
          CCALL32 _KSEMRequestMutex,<<offset FLAT:_UdelSem>,-1>
          CpuMode Reset

          RestoreReg <ds,es,di,si,cx,bx>
          LeaveProc
          ret
EndProc   _SEM_REQUEST


Procedure _SEM_RELEASE, NEAR

          EnterProc
          SaveReg <bx,cx,si,di,es,ds>

          .386P
          CpuMode 386
          FlatContext <DS, ES>,BX
          CCALL32 _KSEMReleaseMutex,<offset FLAT:_UdelSem>
          CpuMode Reset

          RestoreReg <ds,es,di,si,cx,bx>
          LeaveProc
          ret
EndProc   _SEM_RELEASE

HIGH3CODE  ends
           end


