        page    ,132
        title   DemFile2.asm

;***EM  demfile2.asm
;
;       SUMMARY
;           DOS Emulation File System Support
;
;       NOTES
;
;       REVISIONS
;
;Local  DCR/
;Tag    PTR     Who     When
;               danno   31-Jan-1989
;                   Created for MVDM
;
;********************************************************************** ;BN001;
; 001   DCR 1360     Mark Rogalski                                      ;BN001;
;                   Add DOS=HIGH support                                ;BN001;
;********************************************************************** ;BN001;
; 15Jul91 - G.L.Fulk                                                    ;BN002;
; Family 1 machines needs to have HMA address normalized so that the    ;BN002;
; selectors avoid the FFFF0h-FFFFFh range of bytes.  This is the ROM    ;BN002;
; BIOS area and is marked in memory management as "uvirt".  The device  ;BN002;
; drivers for family 1 machines are "locking" the entire segment, and   ;BN002;
; a segment value of FFFFh is causing problems.  The technique is to    ;BN002;
; add 10h to the base address and subtract 10h from the offset value.   ;BN002;
;********************************************************************** ;BN002;
; 003   9/8/91  CP20 PTR B726647  Mark Rogalski                         ;BN003;
;       Add spooling support (fool DOS into thinking file is device)    ;BN003;
;********************************************************************** ;BN003;
; 004   9/9/91  CP20 PTR B726695  Bill Madden                           ;BN004;
;   Changed demChMod to restore client's ax register if no error occurs.;BN004;
;   This is needed for Hollywood to work.                               ;BN004;
;********************************************************************** ;BN004;
; 005  9/22/91  CP20 PTR B726258  Mark Rogalski                         ;BN005;
;   Changed demFindFirst to remove DOT from filespec if searching for   ;BN005;
;   Volume ID.                                                          ;BN005;
;********************************************************************** ;BN005;
; 27Sep91 - G.L.Fulk                                                    ;BN006;
; Mapping segment 0 to selector 0 is no good, because selector 0 has    ;BN006;
; a limit length of 0.                                                  ;BN006;
;********************************************************************** ;BN006;
; 02Oct91 - G.L.Fulk                                                    ;BN007;
; Add the Public symbol "demOpenAsciiz".                                ;BN007;
;********************************************************************** ;BN007;
; 008  10/11/91 CP20 PTR B726604  Mark Rogalski                         ;BN008;
;   In DemDupJFT, if handle is for OS/2 device, we need to put V86 SFN  ;BN008;
;   value into EAX so it can be used as an index into the real OS/2 JFT ;BN008;
;********************************************************************** ;BN008;
; 15Oct91 - G.L.Fulk                                                    ;BN009;
; Int 21h, 4Eh (Find First) performs some special action if the volume  ;BN009;
; label bit is turned on.  We need to check the other bits to see if    ;BN009;
; they are also turned on.  If so, then don't do the special label      ;BN009;
; stuff.                                                                ;BN009;
;********************************************************************** ;BN009;
; 010  10/18/91 CP20 PTR B728103  Bill Madden                           ;BN010;
;   Added demMapSegLenCX.                                               ;BN010;
;********************************************************************** ;BN010;
; 011  12/05/91 CP20 PTR B731609  Mark Rogalski                         ;BN011;
;   When searching for volume label, need to reset all other bits       ;BN011;
;   in the attribute field, so file system doesn't get upset.           ;BN011;
;   Copy filespec to our own space when removing dot.                   ;BN012;
;********************************************************************** ;BN012;
; 11Feb92 - G.L.Fulk                                                    ;BN013;
; Hack to fix the FindFirst processing bug in File System.              ;BN013;
;********************************************************************** ;BN013;
; 20Feb92 - G.L.Fulk                                                    ;BN014;
; Don't kill the VDM just because the user is trying to dup an invalid  ;BN014;
; handle.                                                               ;BN014;
;********************************************************************** ;BN014;
; 06Mar92 - G.L.Fulk                                                    ;BN015;
; Background video has a problem of page-not-present faults.  To solve  ;BN015;
; this, if a read or write operation is performed directly to the video ;BN015;
; memory-mapped space I will "touch" each 4K page within the read/write ;BN015;
; buffer space.                                                         ;BN015;
;********************************************************************** ;BN015;
; 28Mar92 - W.W.Madden                                                  ;BN016;
; Only do fix above if the app will actually read or write data to the  ;BN016;
; video buffer (CX ne 0).                                               ;BN016;
;********************************************************************** ;BN016;
; 21May92 - G.L.Fulk                                                    ;BN017;
; Doing a FindNext with a bogus DTA will cause a TRAP E.  Therefore, we ;BN017;
; must check to make sure the DTA has a valid "dem_FF_buffer" address   ;BN017;
; before accessing that memory area.                                    ;BN017;
;********************************************************************** ;BN017;
; 02Jun92 - G.L.Fulk                                                    ;BN018;
; Calls to DemMapSegX with DS=RMSIZE will create a selector with a      ;BN018;
; limit of 0.  This will likely cause a trap in a later worker routine. ;BN018;
;********************************************************************** ;BN018;
; 09Jun92 - G.L.Fulk                                                    ;BN019;
; JFT_Dup_OS2_handle APAR PJ04475.                                      ;BN019;
; DOS handles too big can trap the system.                              ;BN019;
;********************************************************************** ;BN019;
; ??Jul92 - ?                                                           ;BN020;
; Dual threaded VDM.                                                    ;BN020;
;********************************************************************** ;BN020;
; 14Aug92 - G.L.Fulk                                                    ;BN021;
; Instead of using REP MOVSD to move a block, move until asciiz end.    ;BN021;
;********************************************************************** ;BN021;
; 28Aug92 - F. Miro'                                                    ;BN022;
; Calls to filesystem workers updated due to changes for protected      ;BN022;
; filehandles support in the IFSM.                                      ;BN022;
;********************************************************************** ;BN022;
; 24Nov92 - G.L.Fulk                                                    ;56206;
; Added DemTouchHack to account for the bug in DOS's file system, which ;56206;
; our file system people didn't want.                                   ;56206;
;********************************************************************** ;56206;
; 06Dec92 - G.L.Fulk                                                    ;58069;
; A parent opens a file and execs a child process.  The child process   ;58069;
; inherits the open file.  The child issues a close, but the close      ;58069;
; fails.  We were not repairing the PTDA's JFT (DOS's equal to SFT) if  ;58069;
; the close failed.  As a result, the parent now has a handle that      ;58069;
; contains an invalid PTDA JFN.  Change to repair the PTDA JFT.         ;58069;
;********************************************************************** ;58069;
; 08Dec92 - G.L.Fulk                                                    ;57666;
; In DOS you can open a file R/W to a R/O device (ie. CDROM).  The OS/2 ;57666;
; file system fails with access denied.  Add a hack to fix this issue.  ;57666;
; If the open fails, and it was a R/W request, then check the FSDname.  ;57666;
; If the FSDname is "CDFS" then change the mode to a R/O access and     ;57666;
; try the open again.                                                   ;57666;
;********************************************************************** ;57666;
; 21Jan93 - G.L.Fulk                                                    ;53991;
; Windows appears to prepend UNC names with a drive letter.  Check for  ;53991;
; a drive letter on a UNC asciiz name and drop the drive letter.        ;53991;
;********************************************************************** ;53991;
; 21Jan93 - G.L.Fulk                                                    ;60568;
; Similar to the problem above is QBasic's bug of prepend named pipe    ;60568;
; open calls.                                                           ;60568;
;********************************************************************** ;60568;
; 25Jan93 - G.L.Fulk                                                    ;60303;
; The touch hack from above (56206) has a bug.  The call to FileTimes   ;60303;
; in filesys doesnot preserve the BX register (file handle).  As a      ;60303;
; result the following Close operation closes a bogus handle.           ;60303;
;********************************************************************** ;60303;
;62131 - Carlos A. Romero 03/18/93 - Copy EAs from Windows File Manager ;62131;
;********************************************************************** ;62131;
;  29Jul93 - J.M.Hare    defect 71358                                   ;BN040;
; Add propogating of DOSFLAG through files system for exec_only test.   ;BN040;
;***********************************************************************;BN040;
;  09/07/93  Richard Mulder   Defect 73436                              ;73436;
; Move FindFirstDTA structure to finddta.inc file.                      ;73436;
;***********************************************************************;73436;
;  10/05/93  Change Team  Defect 74402                                  ;74402;
; Added check to demOpen for Volume Id attribute byte.  If present,     ;74402;
;  added code to format an FCB and call demFCBOpen to create the        ;74402;
;  volume identifier.                                                   ;74402;
;***********************************************************************;74402;
; 01/12/94 Marc Pierre-Louis Change Team Defect 76963                   ;76963
;Changed the call of demFCBOpen to W_SetFSInfo because demFCBOpen       ;76963
;was failing when the disk already had a label. W_SetFSInfo is the API  ;76963
;that is used by the LABEL utility to update/change volume labels.      ;76963
;***********************************************************************;76963
;  01/27/94  Change Team  Defect 77963  (REGR:71358)                    ;77963;
; Removed LocalVar "dop_execdw" from procedure demOpen to prevent       ;77963;
; problem with SpeechViewer Sound Awareness being unable to communicate ;77963;
; with audio device driver.                                             ;77963;
;***********************************************************************;77963;
; 03/08/94  wdm  merged 77963 with performance work                     ;77963;
;***********************************************************************;95072;
; 09/07/94  whh  95072 - labels not generated correctly                 ;95072;
;***********************************************************************
; 09/19/94  bjn  change segment names for page tuning
;***********************************************************************
; 11/17/94  ChgTm  Defect 81783  (REGR:74402)                           ;81783;
; Defect 74402 moved the demOpenAsciiz code after the check for names   ;81783;
; beginning c:\pipe\. To avoid problems opening pipes, moved the        ;81783;
; demOpenAsciiz code back to where it was before defect 74402.          ;81783;
;***********************************************************************;81783;
; 05/16/95  Change Team Defect 120690                                   ;120690
; Dem_FindFirst, delay removal of dot in volume labels until            ;120690 112810
; dos\filesys\search.asm(w_3xFindFirst) so that long labels with dots   ;120690 112810
; are properly found.                                                   ;120690 112810
;***********************************************************************;123540
; 06/28/95  Change Team Defect 123540                                   ;123540
; Checking the limit in selectors returned to demGetBaseName from       ;123540
; demMapESDI and demMapDS.  This check may need to be added elsewhere   ;123540
; in this program where demMapESDI and demMapDS are used.               ;123540
;***********************************************************************;123540
;  11/27/95 MLM         Defect 72417                                    ;72417
;  moved from PTDA to TCB: DTAddr, pSrchBuf                             ;72417
;***********************************************************************;72417
;
;
;
;   Throughout the routines in this file, when loading registers
;   from the client stack frame, we will perform a 32-bit load.
;   Generally, the upper-16 bits of the register are ignored and
;   only the lower 16-bits are needed.  This is done only to avoid
;   an override.
;
;   When storing registers into the stack frame, however, we always
;   perform 16-bit stores, since the upper 16-bits of the 32-bit
;   registers are reserved *exclusively* for DOS applications.
;

INCL_NONE       equ     1                       ; don't include everything
INCL_TYPES      equ     1                       ; include basic types
INCL_DEF        equ     1                       ; include typedef macros
INCL_VDHALL     equ     1                       ; include VDH services

.xlist
include virtsym.inc                   ;62131
include vmowner.inc                   ;62131
include fnomvdm.inc
include dosseg.inc
include basemaca.inc
include osmaca.inc
include osconst.inc
include dossymc.inc
include infoseg.inc
include sigdef.inc
include except.inc
include pgexport.inc
include vmexport.inc
include selxport.inc
include tkexport.inc
include dirent.inc
include curdir.inc
include find.inc
include screen.inc
include sft.inc
include sem.inc
include seldesc.inc
include protmode.inc
include chardd.inc
include dos3dev.inc
include filesys.inc
include inbuf.inc
include dbcs.inc
include argframe.inc
include opncreat.inc
include dem.inc
include error.inc
include extattr.inc
include kmode.inc
include mult.inc
include pdb.inc
include mi.inc
include vpb.inc
include fsc.inc
include mvdm.inc
include sysentry.inc
include devsym.inc
include struc30.inc
include vdmvdh.inc                                                      ;BN020;
include mft.inc                                                         ;56206;
include finddta.inc                                                     ;73436;
include extfcb.inc                                                      ;74402;
.cref
.list

        ModName  demfile2, FNO_DEMFILE2_ASM

        CpuMode 386


        EXTRN   _demAllocBlkVMKHBI:DWORD                                ;BN013;
        EXTRN   _demFindFirstHack_head:DWORD                            ;BN013;
        ReferTask       ptda_handle,WORD                                ;BN013;
        EXTRN32         _VMAllocKHB                                     ;BN013;
        EXTRN32         _VMFreeKHB                                      ;BN013;
        ReferTask       JFN_Length,WORD                                 ;BN019;
        ReferTask       JFN_pTable,DWORD
        ReferTask       JFN_Flg_Ptr,DWORD
        ReferTask       CurrentPDB,WORD
                                                                        ;72417;
        ReferTask       CurrTCB,WORD
        ReferTask       LCurDrv,BYTE                                    ;57666;
        ReferGDT        GDT_VPB,WORD
        EXTRN16         DriveFromText
        EXTRN16         GetDeviceName
        EXTRN16         w_qFSAttach                                     ;57666;
        EXTRN16         w_OpenCreate
        EXTRN16         SFFromHandle
        EXTRN16         SFFromSFN
        EXTRN16         pJFNFromHandle:NEAR
        EXTRN16         w_DiskReset
        EXTRN16         w_Set_Default_Drive
        EXTRN16         ReadDo
        EXTRN16         w_Close
        EXTRN16         FileTimes
        EXTRN16         w_LSeek
        EXTRN16         Dir_Search_First
        EXTRN16         Dir_Search_Next
        EXTRN16         w_3xFindFirst
        EXTRN16         w_3xFindNext
        EXTRN16         w_NameTrans
        EXTRN16         w_ChMod
        EXTRN16         w_FSCtl
        EXTRN16         EAOP_selector_alloc
        EXTRN16         EAOP_selector_free
        EXTRN16         DOS_Dup
        EXTRN16         w_3xBufReset
        EXTRN16         Ext_Information
        EXTRN16         FStrCpy
        EXTRN16         w_3xCreateNew
        EXTRN16         w_3xEnumAttrib
        EXTRN16         w_CreateTempFile
        EXTRN16         MakeFcb
        EXTRN16         w_LockOper
        EXTRN16         w_Get_Drive_Freespace
        EXTRN16         UnPack
        EXTRN16         SegAlloc2:FAR              ;62131
        EXTRN16         SegFree2:FAR               ;62131
;76963  EXTRN           demFCBOpen:NEAR            ;74402
        EXTRN           _demParseLabel:NEAR        ;95072
        EXTRN16         w_QPathInfo:FAR            ;76963
        EXTRN16         w_SetFSInfo:FAR            ;76963
        EXTRN16         StrLen:FAR                 ;76963
        EXTRN           FSD_Read:NEAR
        EXTRN           FSD_Write:NEAR

DefCode IMPORT, GLOBAL, C
DefFn   SELSetDescInfo
EndCode

DefCode IMPORT, GLOBAL, PASCAL
DefFn   VDHKillVDM
EndCode

DefData IMPORT, INSTANCE, C
ULONG   vdmid_RMSIZE
EndData

DefData IMPORT, SWAP, C                                                 ;BN020;
PFN     pfnSlaveRequest                                                 ;BN020;
EndData                                                                 ;BN020;
                                                                        ;BN020;
DefData IMPORT, SWAPINST, C                                             ;BN020;
USHORT  flVDMDEM                                                        ;BN020;
EndData                                                                 ;BN020;

DefData EXPORT, SWAPINST, C
USHORT  aseldemTemp,,(CSELDEMTEMP+1)
EndData

        FARCODE HIGH32
DefCode PRIVATE, SWAP, PASCAL

SWAP32_22  segment  ;  wdm merge 77963 with performance work
;***LP  demGetBaseName - Get the base name from a full filespec
;
;       This routine extracts the base name from a full filespec,
;       and converts it to upper case.
;
;       ENTRY
;           EBX
;               V86 Register Frame (VSF)
;           VSF(DS:DX)
;               Source pathname
;           VSF(ES:DI)
;               Destination buffer for the base name (9 bytes)
;
;       EXIT
;           SUCCESS
;               CF = 0
;               Buffer at VSF(ES:DI) = base name (sans "." and extension)
;           ERROR
;               CF = 1
;
;               (Not a device name)
;
;       CONTEXT
;           Called from Virtual Mode
;           Executes in Kernel
;
;       STEPS
;           skip possible drivespec and ":"
;           GetDeviceName
;           return temp
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;           DriveFromText
;           GetDeviceName
;           demMapESDI
;           demMapDS
;
;       USES
;           EAX,EBX,ECX,EDX,ESI,EDI,DS,ES
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING
        align 4

Procedure demGetBaseName,near
        movzx   edi, di                 ; (EDI) = zero extended         - 123540
        movzx   esi,si                  ; (ESI) = zero extended         - 123540

        call    demMapESDI              ; (ES:DI) -> destination buffer

        mov     cx, es                  ; Verify that the segment limit - 123540
        xor     eax, eax                ;                               - 123540
        lsl     ax, cx                  ; returned from demMapESDI is   - 123540
        cmp     eax, edi                ; not past the limit of ES      - 123540
        jle     gbn10                   ; Error, set carry              - 123540

        ASSUME  ES:NOTHING
        mov     si,[ebx].vsf_dx         ; (SI) = user's DX register
        call    demMapDS                ; (DS:SI) -> points to the object

        mov     cx, ds                  ; Verify that the segment limit - 123540
        xor     eax, eax                ;                               - 123540
        lsl     ax, cx                  ; returned from demMapDS   is   - 123540
        cmp     eax, esi                ; not past the limit of DS      - 123540
        jle     gbn10                   ; Error, set carry              - 123540

        ASSUME  DS:NOTHING
        CALL16  DriveFromText           ; (DS:SI) -> points after drive
        inc     al
        jz      short gbn10             ; Exit if bad drive letter
        SaveReg <es,di>
        CALL16  GetDeviceName           ; (DS:SI) -> last component
        RestoreReg <di,es>              ; (ES:DI) -> destination buffer
        jc      short gbn10

;       (DS:SI) = last component name
;       (ES:DI) = destination buffer

        movzx   esi,si                  ; (ESI) = zero extended
        movzx   edi,di                  ; (EDI) = zero extended
        mov     eax,esi                 ; (EAX) = begining of string
        CALL16  FStrCpy
        dec     esi                     ; (ESI) = point to NULL
        sub     esi,eax                 ; (ESI) = size = end - beginining
        mov     ecx,DEVNAMELEN          ; (ECX) = max device length
        sub     ecx,esi                 ; (ECX) = number of chars to pad
        .if     ae                      ; jump if greater than the max
          ; Pad device name to 8 chars (DEVNAMELEN) with spaces
          dec     edi                     ; (EDI) = end of string (at NULL)
          mov     al,' '
          rep     stosb
          xor     al,al
          stosb
          clc
        .else
gbn10:    stc
        .endif
        ret
EndProc   demGetBaseName
SWAP32_22 ENDS       ;  wdm merge 77963 with performance work


;***LP  demCopyEAs - Copy Extended Attribute Information
;
;       Copy Extended Attribute Information
;
;       ENTRY
;           AL = 14
;           VSF(CX)
;               Size of EAs buffer
;           VSF(BX)
;               Handle (JFN) of file to query EAs (not fake handle)
;           VSF(DX)
;               Handle (JFN) of file to set Eas (not fake handle)
;
;       EXIT
;           SUCCESS
;               CF = 0
;               EA's returned or updated
;           FAILURE
;               CF = 1
;               AX = error code
;
;       HARD ERROR EXIT
;           CF = 1
;           AX = 0FFFFh
;
;       CONTEXT
;           Called from Virtual Mode
;           Executes in Kernel
;
;       STEPS
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;           demMapESDI
;           demMapDS
;           Ext_Information
;
;       USES
;           EAX,EBX,ECX,EDX,ESI,EDI,EBP,DS,ES
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING
        align   4

EAOP_S struc
dummy1     dd 0
FEAList    dd 0
dummy2     dd 0
EAOP_S ends


Procedure demCopyEAs, near
LocalVar  fhSource, WORD                   ;
LocalVar  fhDest,   WORD                   ;
LocalVar  EAsize,   WORD
LocalVar  EAOPST, <size EAOP_S>

;Extract register information that we need here
        mov     edx,[ebx].vsf_edx
        mov     ecx,[ebx].vsf_ecx
        mov     ebx,[ebx].vsf_ebx

        EnterProc <bx, dx, cx>

;Allocate a temporary buffer to hold EAs
        xor     ax,ax
        mov     bx,cx                   ; AX:BX = size of segment to alloc
        mov     ch,D_DATA0
        mov     cl,SA_GDT               ; SFlags and AFlags
                                        ; dx is not used (?)
        mov     si,HF_SWAPPABLE
        mov     di,FSEATMPOWNER
        CALL16  SegAlloc2
        mov     ax,ERROR_NOT_ENOUGH_MEMORY  ; In case SegAlloc returned error
        jc      demExit                     ; Error, then exit

;
;Save FEAList buffer in EAOP structure
        xor     di,di
        mov     [EAOPST.FEAList].Segmt, bx
        mov     [EAOPST.FEAList].Offst, di
        mov     es, bx

;Set FEAList size in EAOP structure
        mov     ax, [EAsize]       ;
        mov     es:[di], ax        ;
        mov     es:[di+2], di      ;

;       ES:DI-> EAOP info buffer
        push    ss
        pop     es
        lea     di, EAOPST

;Get EAs from  destination file
        mov     ax, 8002H          ;AH= 80H tells EXT_Information not to
        mov     cx, 12             ;convert EAOP pointer to selector
        mov     dx, 4
        mov     bx, [fhSource]
        CALL16  Ext_Information
        jc      demExit2

;
;       ES:DI-> EAOP info buffer
        push    ss
        pop     es
        lea     di, EAOPST

;Now copy EAs to destination file
        mov     ax, 8003H          ;AH= 80H tells EXT_Information not to
        mov     cx, 12             ;convert EAOP pointer to selector
        mov     dx, 2
        mov     bx, [fhDest]
        CALL16  Ext_Information

;Deallocate temporary buffer and leave
demExit2:
        mov     ax, [EAOPST.FEAList].Segmt  ; free temporary buffer
        CALL16  SegFree2
demExit:
        LeaveProc
        ret
EndProc demCopyEAs

SWAP32_23 segment         ;   wdm merge 77963 with performance work
;***LP  demDupJFT - Duplicate a JFT
;
;       ENTRY
;           EBX = Address of VSF
;           VSF(ES)
;               Segment of new PDB
;           VSF(CS:DI)
;               Address of RMDevInfoHandle table (virtual mode SFT)
;
;       EXIT
;           New JFN Table is initialized
;               Duplicate the first 20 handles from old to new JFT
;               If a duplication fails, just leave the new handle free
;
;       CONTEXT
;           Called from Virtual Mode
;           Executes in Kernel
;
;       STEPS
;           prmdi = PFROMVP((vsf_cs << 4) + vsf_di)
;           pCurrentJFN_Table = PFROMVP((CurrentPDB<<4)->PDB_JFN_Pointer)
;           pNewJFN_Table = (vsf_es << 4)+PDB_JFN_Table
;           pNewPDB->PDB_JFN_Pointer = pNewJFN_Table
;           pNewPDB->PDB_JFN_Length = FILPERPROC
;           setmem(pNewJFN_Table, FILPERPROC, 0xFF)
;
;           /* We only DUP the first 20 handles, and skip RM devices */
;           for VJFN = 0 .. (FILPERPROC-1)  -->
;               VSFN = pCurrentJFN_Table->[VJFN]
;               iRMDI = VSFN - VSFN_DEV
;               if (VSFN != 0xFF) -->
;                   /* Ignore RM-only devices */
;                   if (VSFN < VSFN_DEV)   /* A file ? */
;                     || (prmdi[iRMDI].devPtr.HIword == -1) -->
;                       SFN = pPTDACur->JFN_pTable[VSFN]
;                       if (SFN == -1) -->
;                           demTerminate
;                       if (pPTDACur->JFN_Flg_Ptr[SFN] & JFN_DIH) == 0 -->
;                           pSF = SFFromSFN(SFN)
;                           DOS_Dup
;
;       NOTES
;           This routine is only part of the process.  After
;           Performing the DUP here, we must complete the DUP
;           on RM-only files in V86 mode.
;
;       WARNINGS
;           None
;
;       CALLS
;           SFFromSFN
;           DOS_Dup
;
;       USES
;           EAX,EBX,ECX,EDX,ESI,EDI,EBP,ES,FS
;
        ASSUME  DS:FLAT,ES:FLAT,SS:TASKAREA,FS:NOTHING,GS:NOTHING
        align   4

Procedure demDupJFT,near

LocalVar  prmdi,DWORD                   ;flat address of RMDevInfoHandle
LocalVar  pCurrentJFN_Table,DWORD       ;flat address of the old JFT
LocalVar  pNewJFN_Table,DWORD           ;flat address of the new JFT

        EnterProc

;------ prmdi = PFROMVP(vsf_cs,vsf_di)
        movzx   edx,[ebx].vsf_cs
        movzx   eax,[ebx].vsf_di
        shl     edx,4
        add     edx,eax
        mov     prmdi,edx               ;flat addr of RMDevInfoHandle

;------ pCurrentJFN = PFROMVP((CurrentPDB<<4)->PDB_JFN_Pointer)
        mov     ax,ss:[CurrentPDB]      ; we know eax.hiword == 0
        shl     eax,4                   ; eax=flat address of old PDB
        movzx   edi,[eax].PDB_JFN_Pointer.hiword
        movzx   edx,[eax].PDB_JFN_Pointer.loword
        shl     edi,4
        add     edi,edx
        mov     pCurrentJFN_Table,edi   ;flat addr of the old JFT

;------ PDB_JFN_Pointer = &(PDB_JFN_Table)
        mov     ax,[ebx].vsf_es
        movzx   edi,ax
        shl     edi,4                   ; EDI = pNewPDB
        mov     [edi].PDB_JFN_Pointer.loword,PDB_JFN_Table
        mov     [edi].PDB_JFN_Pointer.hiword,ax

;------ PDB_JFN_Length = FILPERPROC
        mov     [edi].PDB_JFN_Length,FILPERPROC

;------ pNewJFN_Table = (vsf_es << 4)+PDB_JFN_Table
        add     edi,PDB_JFN_Table
        mov     pNewJFN_Table,edi       ;flat addr of new JFT

;------ fill the new JFT with all FFh.
        mov     eax,-1
        mov     ecx,FILPERPROC/4
        rep     stosd

;------ initialize variables for main loop
        mov     ecx,FILPERPROC          ; duplicate only the 1st 20 handles
        mov     esi,pCurrentJFN_Table   ; EDI=&old JFT
        mov     edi,pNewJFN_Table       ; EDI=&new JFT

;------ main loop
        .repeat
          xor     eax,eax
          lodsb
          ;EAX=old JFN
          .if     <AL ne SFN_NULL>      ; Skip if not in use (AL=-1)
            .if     <al ae VSFN_DEV>    ; A DOS or OS2 device? (AL>=D0h)

              sub     ax,VSFN_DEV       ; Get RMDI index
              mov     ebx,eax
              shl     ebx,3  ;== *(size rmdi)
              add     ebx,prmdi         ;EBX=&RMDevInfoHandle[x]

              ;If an open handle has rmdi_refcnt==0, then that's illegal.
              ;That means an open handle exists for a file that nobody is
              ;using.  The old method was to kill the VDM, but now we will
              ;just ignore the problem by not dupping this JFN.  Instead
              ;we'll just force this handle to be free.  (JFN=free=-1)
              cmp     [ebx].rmdi_refcnt,0
              je      jftie_rmdi_refcnt_0       ;--- JFN=D0..FEh, refcnt=0

              ;If this is a DOS device then we will let the DOS Kernel
              ;handle the duplicating of it's handles.  We'll just fill
              ;in the new JFN with free (=-1).
              cmp     [ebx].rmdi_devPtr.loword,-1
              jne     jft_DOS_device            ;--- JFN=D0..FEh, DOS device

              mov     ax,[ebx].rmdi_devPtr.hiword   ;get the OS/2 device handle
            .endif

            ;AX=OS/2 handle

            call    jft_dup_OS2_handle

          .else
jftie_rmdi_refcnt_0:      ;--- JFN=D0..FEh, refcnt=0
jft_DOS_device:           ;--- JFN=D0..FEh, DOS device
            inc     edi   ;--- JFN=FFh
          .endif
        .loop
        xor     eax,eax                 ; Always succeeds (or panics)
        LeaveProc
        ret
EndProc   demDupJFT
SWAP32_23 ENDS          ;  wdm merge 77963 with performance work


SWAP32_26 segment

;       We need to preserve es:edi, ds:esi, and ecx here.

Procedure jft_dup_OS2_handle,near

        ;------ See if handle is in a valid range                       ;BN019;
        .if     <AX b <ss:[JFN_Length]>>                                ;BN019;

          xor     ebx,ebx
          LFS     BX,ss:[JFN_pTable]
          ;FS:EBX=&PTDA's JFT

          mov     dx,fs:[ebx+eax*2]       ; Get the real SFN
          ;DX=PTDA's JFT[os2 handle]=SFN

          ;------ Is the SFN open?
          .if     <dx ne SFN_NULL>

            LFS     BX,ss:[JFN_Flg_Ptr]
            ;FS:EBX=JFT_flags[os2 handle]

            ;------ test the inherit bit
            .if     <BIT <byte ptr fs:[ebx+eax]> nand JFN_DIH>

              SaveReg <ds,es,edi,esi,ecx>
              mov     bx,dx
              CALL16  SFFromSFN               ; Get the SF pointer
              ASSUME  DS:NOTHING,ES:NOTHING
              .if     c
                RestoreReg  <ecx,esi,edi,es,ds>
                ASSUME  ES:FLAT,DS:FLAT
;;;;;;;;;;;;;;; Panic   "demDupJFT: SFFromSFN"
              .else
                ASSUME  DS:NOTHING,ES:NOTHING
                CALL16  DOS_Dup
                RestoreReg  <ecx,esi,edi,es,ds>
                ASSUME  ES:FLAT,DS:FLAT
                .if     nc
                  stosb
                  ret
                .endif
              .endif
            .endif
          .endif
        .endif                                                          ;BN019;

        inc     edi
        ret
EndProc jft_dup_OS2_handle,NoCheck
SWAP32_26 ends

;;;jftie_rmdi_refcnt_0:
;;;jftie_sfn_FFFF:
;;;jftie_dup_failed:
;;      xor     eax,eax
;;      PCall   VDHKillVDM, <eax>
;;      jmp     short jft4


SWAP32_22  segment    ;   wdm merge 77963 with performance work
;***LP  demOpen - Open Handle
;
;       ENTRY
;           VSF(DS:SI)
;               Address of PathSpec
;           VSF(BX)
;               Open Mode (See NOTES)
;           VSF(CX)
;               Create File Attributes (See NOTES)
;           VSF(EDL)                                                exec_only BN040
;               exec_only flag from exec_open via $open_exec_only   exec_only BN040
;           VSF(DX)
;               Open File Flags (See NOTES)
;           VSF(ES:DI)
;               Address of extended attributes buffer (See NOTES)
;           VSF(AL)
;               0 - No EA's
;               1 - EA's specified
;
;       EXIT
;           SUCCESS
;               CY = 0
;               AX = Assigned Open Handle
;               VSF(BX) = DOS-style SFT flags
;               VSF(CX) = open disposition (created/replaced/existed)
;           FAIL
;               CY = 1
;               AX = system status code
;           HARD ERROR
;               CY = 1
;               AX = 0FFFFh
;
;       CONTEXT
;           Called from Virtual Mode
;           Executes in Kernel
;
;       STEPS
;
;       NOTES
;           See the DosOpen2 API for more information on
;           these parameters.
;
;       WARNINGS
;           None
;
;       CALLS
;           demMapDS, demMapSegESDI
;           w_OpenCreate
;
;       USES
;           EAX,EBX,ECX,EDX,ESI,EDI,DS,ES
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING
        align   4

Procedure demOpen,near

LocalVar  dop_pvsf,DWORD
LocalVar  dop_usAction,WORD                     ; save open disposition
LocalVar  dop_segFEA,WORD                       ; save FEA & GEA segments
LocalVar  dop_segGEA,WORD
LocalVar  dop_ArgFrame,<size Open3Struc>        ; frame to pass to w_OpenCreate
;opn3s_Reserved   dd ?             ; reserved dword
;opn3s_FileHandleLockIDPtr dd 0    ; Pointer to FileHandleLockID buffer
;opn3s_EABufPtr   dd 0|*vsf(es:di) ; Pointer to EA buffer
;opn3s_Mode       dw vsf(bx)       ; Open mode for file
;opn3s_Mode2      dw 0             ; high word of OpenMode
;opn3s_Flag       dw vsf(dx)       ; Flags for open
;opn3s_Attrs      dw vsf(cx)       ; File attribute
;opn3s_Size       dd 0             ; Size of file
;opn3s_ActionPtr  dd ?             ; Pointer to location for returned action
;opn3s_HandlePtr  dd ?             ; Pointer to location for returned handle
;opn3s_NamePtr    dd *vsf(ds:si)   ; Pointer to file name
          dop_qFSAsize equ 64                                           ;57666;
LocalVar  dop_qFSAszDeviceName,DWORD                                    ;57666;
LocalVar  dop_qFSABuffer,<dop_qFSAsize>                                 ;57666;
LocalVar  dop_qFSABufferLen,DWORD                                       ;57666;
;77963 LocalVar  dop_execdw,DWORD       ;                        exec_only BN040
LocalVar  dop_exec,WORD                 ;                        exec_only BN040
;                                                                       ;74402
; Extended FCB for volume name creates                                  ;74402
;                                                                       ;74402
;76963 LocalVar  ext_fcb,<size sys_ext_fcb>                             ;74402
          dop_Label_MaxLen    equ 12    ;11 Chars + Null byte           ;76963
          dop_InfoLevel       equ  2    ;                               ;76963
LocalVar  dop_LabelBuffer,<dop_Label_MaxLen+1>                          ;76963
LocalVar  dop_PathInfo,<size inbuf>                                     ;76963
          PathInfoBufSize equ <size inbuf>                              ;76963

        EnterProc <ebx> ;save EBX into dop_pvsf

;------ initialize Exec_only flag from the loader                exec_only BN040
        mov    eax,[ebx].vsf_edx        ;only need EdX part      exec_only BN040
;77963  mov    dop_execdw,eax           ;                        exec_only BN040
;77963  xor    ax,ax                    ;                        exec_only BN040
;77963  mov    ax,word ptr dop_execdw+2 ;                        exec_only BN040
        shr    eax,16                   ;move Eax part to ax     exec_only 77963
        mov    dop_exec,ax              ;                        exec_only BN040

;------ initialize Open3Struc values
        mov     eax,[ebx].vsf_ebx       ;only need AX part
        mov     dop_ArgFrame.opn3s_Mode,ax

        mov     eax,[ebx].vsf_ecx       ;only need AX part
        and     eax,attr_changeable + attr_volume_id      ; added vol_id  74402
        mov     dop_ArgFrame.opn3s_Attrs,ax

        xor     eax,eax
        mov     dop_ArgFrame.opn3s_FileHandleLockIDPtr,eax ; assume no LockID ptr
        mov     dop_ArgFrame.opn3s_EABufPtr,eax ; assume no EA's
        mov     dop_ArgFrame.opn3s_Size,eax     ; size always zero with $Creat
        mov     dop_ArgFrame.opn3s_Mode2,ax     ; openmode2 not yet supported

        mov     eax,[ebx].vsf_edx       ;only need AX part
        mov     dop_ArgFrame.opn3s_Flag,ax

;------ Process EAs if VSF(AL)=1 and VSF(ES:DI)<>0
        mov     ax,[ebx].vsf_es
        or      ax,[ebx].vsf_di
        .if     nz and                  ; skip mapping if NULL addr
        .if     <<[ebx].vsf_al> eq 1>   ; EA's specified ?
          call    demMapESDI            ; ES:DI = EA address
          assume  es:nothing
          mov     dop_ArgFrame.opn3s_EABufPtr.Offst,di                  ;BN022;
          mov     dop_ArgFrame.opn3s_EABufPtr.Segmt,es                  ;BN022;
          .if     <DI a <(0FFFFh - (size EAOP)) + 1>>  ; segment overrun ?
            mov     eax,ERROR_BAD_LENGTH
            stc                                     ; SB PTRB708452
            jmp     dop5
          .endif

          mov     ax,es:[di].eaop_fpGEAlist.Segmt
          mov     dop_segGEA,ax
          mov     ax,es:[di].eaop_fpFEAlist.Segmt
          mov     dop_segFEA,ax
          CALL16  EAOP_selector_alloc             ; allocate sels for the EA's
        .endif

;------ Get the asciiz name in selector:offset form
        movzx   esi,[ebx].vsf_si                ; (SI) = path offset    ;53991;
        mov     cx,ds                           ; save old ds           ;74402

        call    demMapDS                        ; get 16:16 addr of the string

;81783  This public symbol contains the ASCIIZ name to open.            ;BN007;
;81783  Recommended Kernel Debugger statement:                          ;BN007;
;81783          BP demOpenAsciiz "da ds:si;g"                           ;BN007;
;81783  PUBLIC  demOpenAsciiz                                           ;BN007;
;81783 demOpenAsciiz:                                                   ;BN007;
;81783  mov     dop_ArgFrame.opn3s_NamePtr.Segmt,ds                     ;BN022;
;81783  mov     dop_ArgFrame.opn3s_NamePtr.Offst,si                     ;BN022;

        assume  ds:nothing
                                                                        ;53991;
;------ Look for "?:\\network"                                          ;53991;
        .if     <<byte ptr [esi]> ne 0> and                             ;53991;
        .if     <<word ptr [esi]+1> eq "\:">                            ;60568;
          .if     <<byte ptr [esi]+3> eq "\">                           ;53991;
            inc     esi                                                 ;53991;
            inc     esi                                                 ;53991;
          .else                                                         ;60568;
            mov     eax,dword ptr [esi]+3                               ;60568;
            or      eax,20202020h       ;convert to lowercase           ;60568;
            .if     <eax eq "epip"> and                                 ;60568;
            .if     <<byte ptr [esi]+7> eq "\">                         ;60568;
              inc     esi                                               ;60568;
              inc     esi                                               ;60568;
            .endif                                                      ;60568;
          .endif                                                        ;53991;
        .endif                                                          ;53991;
                                                                        ;53991;
;       This public symbol contains the ASCIIZ name to open.            ;81783;
;       Recommended Kernel Debugger statement:                          ;81783;
;               BP demOpenAsciiz "da ds:si;g"                           ;81783;
        PUBLIC  demOpenAsciiz                                           ;81783;
demOpenAsciiz:                                                          ;81783;
        mov     dop_ArgFrame.opn3s_NamePtr.Segmt,ds                     ;81783;
        mov     dop_ArgFrame.opn3s_NamePtr.Offst,si                     ;81783;
                                                                        ;81783;
;       Check to see if we're creating a volume label                   ;74402
;                                                                       ;74402
        mov     ax,dop_ArgFrame.opn3s_Attrs     ; get the attributes    ;74402
        and     ax,attr_volume_id               ; is volume bit set?    ;74402
        jz      demOpenTryAgain                 ; no, continue          ;74402
                                                                        ;74402
;       This is a volume label create request.  We'll just fill out an  ;74402
;       FCB and pass this along to demFCBOpen, which can handle this    ;74402
;       with its eyes closed.                                           ;74402
                                                                        ;74402
        PUBLIC  demOpenLabel                                            ;74402
demOpenLabel:                                                           ;74402
;76963  lea     edx,ext_fcb                     ; load base of ext FCB  ;74402
;76963  mov     [edx].ext_fcb_ff,0ffh           ; extended FCB          ;74402
;76963  mov     [edx].ext_fcb_attrib,attr_volume_id ;only set volid bit ;74402
                                                                        ;74402
        .if     <<byte ptr [esi]+1> eq ":">     ; drive specified?      ;74402
          mov   al,byte ptr [esi]               ; convert to drive #    ;74402
          or    al,020h                         ; convert to lower case ;74402
          sub   al,'a'-1                        ; a=1, b=2, etc         ;74402
          inc   esi                             ; point past it         ;74402
          inc   esi                                                     ;74402
        .else                                                           ;74402
          xor   al,al                           ; set to 0 (def. drive) ;74402
        .endif                                                          ;74402
        mov     bx,ax                           ;bx->drive #            ;76963
        mov     edi,esi                         ;get ready to get len.  ;76963
        push    ds                                                      ;76963
        pop     es                                                      ;76963
        xor     ecx,ecx                                                 ;76963
        CALL16  StrLen                          ;Get len. of user buff. ;76963
        mov     edi,esi                                                 ;76963
        add     esi,ecx                        ;point to end of buff.   ;76963
        dec     esi                            ;position at null byte   ;76963
        std                                    ;change direction flg    ;76963
                                               ;keep checking until     ;76963
                                               ;a "\" or a ":" is found ;76963
                                               ;or at begining of user  ;76963
                                               ;buffer
dop_getname:                                                            ;76963
        lodsb                                                           ;76963
        .if    <al ne "\"> and                                          ;76963
        .if    <al ne ":"> and                                          ;76963
        .if    <esi ge edi>                    ;not begining of buff?   ;76963
            jmp     dop_getname                                         ;76963
        .endif                                                          ;76963
        cld                                    ;reset direction flg     ;76963
        .if    <al eq ":"> or
        .if    <al eq "\">

            .if     <al eq ":">                ;case of    'd:filename' ;76963
               add     esi,2                   ;position to filename    ;76963
               push    word ptr ds:[esi]       ;save part of the fname  ;76963
               push    esi                     ;save offset             ;76963
               mov  word ptr ds:[esi],005ch    ;set path to 'd:\',0     ;76963
            .else                                                       ;76963
               .if      <esi lt edi >  or      ;case of '\filename'     ;76963
               .if      <<byte ptr ds:[esi]> eq ":"> ;or 'd:\filename'  ;76963
                  add     esi,2                 ;position at file name  ;76963
                  push    word ptr ds:[esi]     ;save content of pos.   ;76963
                  push    esi                   ;save position          ;76963
                  mov     byte ptr ds:[esi],0   ;set end of the path    ;76963
               .else                            ;cases '..\filename'    ;76963
                                                ;or '.\filename'        ;76963
                  inc       esi                   ;position to the \    ;76963
                  push      word ptr ds:[esi]     ;save content of pos. ;76963
                  push      esi                   ;save position        ;76963
                  mov       byte ptr ds:[esi],0   ;set end of the path  ;76963
               .endif                                                   ;76963
            .endif                                                      ;76963
            SaveReg  <ebx,edx,ds,es,esi>                                ;76963
            mov     edx,edi                                             ;76963
            TaskContext <ES>                                            ;76963
            lea    edi,es:[dop_PathInfo]       ;returned buffer         ;76963
            mov    ebx,1                       ;level of info needed    ;76963
            mov    ecx,PathInfoBufSize         ;Size of returned buffer ;76963
            CALL16 w_QPathInfo                 ;Check the path          ;76963
            RestoreReg <esi,es,ds,edx,ebx>                              ;76963
            pop    esi                        ;rest. position           ;76963
            pop    word ptr ds:[esi]          ;rest. its content        ;76963
            .if  c                            ;if path is no good       ;76963
               jmp  dop5                      ;Go return the error      ;76963
            .endif                                                      ;76963
            .if    <<byte ptr ds:[esi]> eq "\">                         ;76963
               inc  esi                       ;position at file name    ;76963
            .endif                                                      ;76963
        .else                                                           ;76963
          inc esi                             ;position to file name    ;76963
        .endif                                                          ;76963

;95072  mov        edi,esi                                              ;76963
;95072  xor        ecx,ecx                                              ;76963
;95072  CALL16     StrLen                      ;Get File name length    ;76963
;95072  cmp        ecx,dop_Label_MaxLen        ;> Max label len. ?      ;76963
;95072  jbe        dop_goodlabel               ;No then we're ok        ;76963
;95072  mov        ax,ERROR_LABEL_TOO_LONG     ;Yes, return error       ;76963
;95072  stc                                                             ;76963
;95072  jmp        dop5                                                 ;76963
;95072                                                                  ;76963
;95072dop_goodlabel:                                                    ;76963
;Format of label Buffer:                                                ;76963
;Byte 0                        : Length of label w/o Null Byte          ;76963
;Byte 2 - Byte(label length)+1 : Label (ASCIIZ)                         ;76963
;                                                                       ;76963
;95072  push       ecx                         ;save label length       ;76963
;95072  TaskContext <ES>                                                ;76963
;95072  lea     edi,[dop_LabelBuffer]          ;di->label buffer        ;76963
;95072  mov     al,cl                          ;cl->label length        ;76963
;95072  dec     al                             ;minus null byte         ;76963
;95072  stosb                                  ;store lab. len.         ;76963
;95072  rep     movsb                          ;save label in buff.     ;76963
;95072  pop     ecx                            ;restore lab. len        ;76963
;95072  TaskContext <DS>                                                ;76963
;95072  lea     dx,[dop_LabelBuffer]                                    ;76963

        PUBLIC  demParseLabel                                           ;95072
demParseLabel:                                                          ;95072
                                               ;esi->src                ;95072
        FlatContext <ds,es>, ax                                         ;95072
        mov     edi, [dop_pvsf]                ;ds:esi -> linear        ;95072
        movzx   eax, [edi].vsf_ds                                       ;95072
        shl     eax, 4                                                  ;95072
        add     eax, esi                                                ;95072
        lea     edi,[dop_LabelBuffer]          ;edi->label buffer       ;95072
        SSToDS <edi>                                                    ;95072
        inc     edi                                                     ;95072
        CCALL32 _demParseLabel <eax,edi>       ;src,dest                ;95072
                                               ;string returned will    ;95072
        TaskContext <ds,es>, ax                ;always be <= 11+1 (null);95072
        lea     edi,[dop_LabelBuffer+1]        ;edi->label buffer       ;95072
        CALL16  StrLen                         ;Get label length        ;95072
                                                                        ;95072
        dec     edi                            ;                        ;95072
        dec     ecx                            ;minus null byte         ;95072
        mov     [edi], cl                      ;length                  ;95072
        mov     edx,edi                        ;buffer                  ;95072

        mov     eax,dop_InfoLevel                                       ;76963
        inc     ecx                            ;cx->Label buff. len     ;76963
;W_SetFSInfo parameters                                                 ;76963
;DS:DX -> Label Buffer                                                  ;76963
;CX    -> Label buffer length                                           ;76963
;AX    -> InfoLevel (Must be 2)                                         ;76963
;BX    -> Drive Number                                                  ;76963
                                                                        ;76963
        CALL16  w_SetFSInfo                                             ;76963
        jmp     dop5                                                    ;74402

;76963  mov   [edx].ext_fcb_drive,al            ; set drive number      ;74402
;76963                                                                  ;74402
;76963 Get the name and extension                                       ;74402
;76963                                                                  ;74402
;76963  .if     <<byte ptr [esi]> eq "\">       ; root dir specified?   ;74402
;76963    inc   esi                             ; bypass it...          ;74402
;76963  .endif                                                          ;74402
;76963                                                                  ;74402
;76963  lea     edi,[edx].ext_fcb_name          ; name location in FCB  ;74402
;76963  push    cx                              ; push saved ds         ;74402
;76963  mov     cx,8 + 3                        ; name.ext (yuck!)      ;74402
;76963                                                                  ;74402
;76963getlabel:                                                         ;74402
;76963  .if     <<byte ptr [esi]> eq 0>         ; end of string?        ;74402
;76963    mov   byte ptr [edi],' '              ; pad with blank        ;74402
;76963  .else                                                           ;74402
;76963    mov   al,byte ptr [esi]               ; get the next char     ;74402
;76963    .if   <al ge 'a'> and                                         ;74402
;76963    .if   <al le 'z'>                     ; is it lower case?     ;74402
;76963      and al,not 020h                     ; convert to upper      ;74402
;76963    .endif                                                        ;74402
;76963    mov   byte ptr [edi],al               ; copy to FCB           ;74402
;76963    inc   esi                           ; ptr to next source char ;74402
;76963  .endif                                                          ;74402
;76963                                                                  ;74402
;76963  inc     edi                             ; ptr to next dest char ;74402
;76963  loop    getlabel                                                ;74402
;76963                                                                  ;74402
;76963  pop     cx                              ; saved ds              ;74402
;76963  .if     <<byte ptr [esi]> ne 0>         ; did we not process    ;74402
;76963                                          ;  the whole string?    ;74402
;76963  dec   edi                             ; point to last dest char ;74402
;76963  mov   byte ptr [edi],'\'              ; bad char, let demFCBOpen;74402
;76963  .endif                                  ;  report the error     ;74402
;76963                                                                  ;74402
;76963  xor     eax,eax                                                 ;74402
;76963  mov     [edx].ext_fcb_EXTENT,ax         ; zero out other fields ;74402
;76963  mov     dword ptr [edx].ext_fcb_reserv,eax                      ;74402
;76963  mov     [edx].ext_fcb_reserv+4,al                               ;74402
;76963  mov     [edx].ext_fcb_RECSIZ,ax                                 ;74402
;76963  mov     [edx].ext_fcb_FILSIZ,ax                                 ;74402
;76963  mov     [edx].ext_fcb_DRVBP,ax                                  ;74402
;76963  mov     [edx].ext_fcb_FDATE,ax                                  ;74402
;76963  mov     [edx].ext_fcb_FTIME,ax                                  ;74402
;76963  mov     [edx].ext_fcb_NR,al                                     ;74402
;76963  mov     [edx].ext_fcb_RR,eax                                    ;74402
;76963                                                                  ;74402
;76963  push    ds                                                      ;74402
;76963                                                                  ;74402
;76963  mov     ds,cx                           ; saved ds              ;74402
;76963  push    [ebx].vsf_ebx                   ; save the regs that    ;74402
;76963  push    [ebx].vsf_edx                   ;  call below...        ;74402
;76963  push    [ebx].vsf_ds                                            ;74402
;76963                                                                  ;74402
;76963  mov     [ebx].vsf_ebx,attr_volume_id    ; set volume id only    ;74402
;76963  pop     [ebx].vsf_ds                    ; pass ptr to FCB in    ;74402
;76963  mov     [ebx].vsf_edx,edx               ;  DS:DX                ;74402
;76963  mov     ax,exist_replace+nexist_create  ; open flags            ;74402
;76963                                                                  ;74402
;76963  push    ds                                                      ;74402
;76963  call    demFCBOpen                                              ;74402
;76963  pop     ds                                                      ;74402
;76963                                                                  ;74402
;76963  pop     [ebx].vsf_ds                                            ;74402
;76963  pop     [ebx].vsf_edx                                           ;74402
;76963  pop     [ebx].vsf_ebx                                           ;74402
                                                                        ;74402
;------ Assign variable for call to file system
demOpenTryAgain:
        mov     dh,byte ptr dop_exec            ; exec_only BN040
        mov     ah,attr_hidden+attr_system+attr_directory ; AH = Sattrib value
        mov     al,OPCR_SATTR_INDIRECT          ; AL=1, call SetAttrib to set
                                                ;       Sattrib
        lea     bx,[dop_ArgFrame]               ; SS:BX = &Argument frame
        mov     dl,IFaceLevel3                  ; DL = DosOpen2Compt IFaceLevel

        ;entry: AL=
        ;       AH=Sattrib
        ;       DL=level
        ;       DH=exec_only flag               ; exec_only BN040
        ;       SS:[BX]=argument frame

        CALL16  w_OpenCreate

        assume  ds:nothing
        ;returns:
        ;CY, AX=error code
        ;NC, AX=handle
        ;    BX=action, 1=existed 2=created 3=replaced

;------ processing for non-error
        pushf                                                           ;57666;
        push    eax                                                     ;57666;
        .if     nc
          ;------ save action taken
          mov     [dop_usAction],bx     ; save creation action

          ;------ get the SFT flags and flags2
          mov     ebx,eax
          CALL16  SFFromHandle          ; get the SF entry
          mov     cx,es:[di].sf_flags

          ; Dos emulation expects handles to LPTx devices to be type
          ; device, but now they may be spool file handles.

          ;------ check for spooled handle, fake spools it into a device
          .if     <BIT <es:[di].sf_flags2> and SFF2_SPOOLED>
            or      ecx,DEVID_DEVICE            ; handle as if device(DCR1499)
          .endif

RM_FLAGS = 0
RM_FLAGS = RM_FLAGS + DEVID_DEVICE_CON_IN       ;0001h
RM_FLAGS = RM_FLAGS + DEVID_DEVICE_CON_OUT      ;0002h
RM_FLAGS = RM_FLAGS + DEVID_DEVICE_NULL         ;0004h
RM_FLAGS = RM_FLAGS + DEVID_DEVICE_CLOCK        ;0008h
RM_FLAGS = RM_FLAGS + DEVID_DEVICE_SPECIAL      ;0010h
RM_FLAGS = RM_FLAGS + DEVID_DEVICE_RAW          ;0020h
RM_FLAGS = RM_FLAGS + DEVID_DEVICE_EOF          ;0040h
RM_FLAGS = RM_FLAGS + DEVID_DEVICE              ;0080h

RM_FLAGS = RM_FLAGS + SF_ISNET                  ;8000h

          and     ecx,RM_FLAGS          ; get DOS-related flags

          FlatContext <ds>,eax
;57666;   mov     eax,ebx               ;get the handle back into AX
          mov     ebx,[dop_pvsf]
          mov     [ebx].vsf_bx,cx       ; return in caller's BX
          mov     cx,[dop_usAction]
          mov     [ebx].vsf_cx,cx       ; return creation action in CX

        .else     near ;The open request failed...                      ;57666;
                                                                        ;57666;
          mov     al,byte ptr dop_ArgFrame.opn3s_Mode                   ;57666;
          and     al,3                                                  ;57666;
          .if     <AL eq 2> near        ;was the request for R/W?       ;57666;
public DemOpen_CDROM_hack                                               ;57666;
DemOpen_CDROM_hack:                                                     ;57666;
            and     byte ptr dop_ArgFrame.opn3s_Mode,0FCh               ;57666;
            LDS     si,dop_ArgFrame.opn3s_NamePtr                       ;57666;
            assume  ds:NOTHING                                          ;57666;
            mov     ax,ds:[si]                                          ;57666;
            push    ss                                                  ;57666;
            pop     ds                                                  ;57666;
            lea     si,dop_qFSAszDeviceName                             ;57666;
            .if     <AH ne ":">                                         ;57666;
              mov     ax,":A"                                           ;57666;
              add     al,ss:[LCurDrv]                                   ;57666;
            .endif                                                      ;57666;
            movzx   eax,ax                                              ;57666;
            mov     ds:[si],eax                                         ;57666;

            mov     eax,ss                                              ;57666;
            ror     eax,10h                                             ;57666;
            mov     ax,si                                               ;57666;
            push    eax                                                 ;57666;
            mov     edx,00010001h                                       ;57666;
            push    edx                                                 ;57666;
            lea     ax,dop_qFSABuffer                                   ;57666;
            push    eax                                                 ;57666;
            lea     ax,dop_qFSABufferLen                                ;57666;
            push    eax                                                 ;57666;
            xor     eax,eax                                             ;57666;
            push    eax                                                 ;57666;
            inc     eax                                                 ;57666;
            mov     bx,sp                                               ;57666;
            mov     dop_qFSABufferLen,dop_qFSAsize                      ;57666;
            CALL16  w_qFSAttach                                         ;57666;
            lahf                                                        ;57666;
            add     sp,+20                                              ;57666;
            .if     <BIT ah nand 1> and                                 ;57666;
            .if     <<word ptr dop_qFSABuffer+7> eq 4> and              ;57666;
            .if     <<dword ptr dop_qFSABuffer+9> eq "SFDC">            ;57666;
              pop     eax                                               ;57666;
              pop     eax                                               ;57666;
              jmp     demOpenTryAgain                                   ;57666;
            .endif                                                      ;57666;

          .endif                                                        ;57666;

        .endif

;------ clean up any EA objects
        .if     <<dop_ArgFrame.opn3s_EABufPtr.Segmt> ne 0>              ;BN022;
                                                 ; skip if EA's not used
          LES     DI,dop_ArgFrame.opn3s_EABufPtr ; else, put segments back
          CALL16  EAOP_selector_free             ; and free the selectors
          mov     ax,dop_segGEA
          mov     es:[di].eaop_fpGEAlist.Segmt,ax
          mov     ax,dop_segFEA
          mov     es:[di].eaop_fpFEAlist.Segmt,ax
        .endif

;------ we're done.
        pop     eax
        popf
dop5:
        LeaveProc
        ret
EndProc   demOpen
SWAP32_22 ENDS        ;   wdm merge 77963 and performance work

;***LP  demCreateNew - create a new file
;
;       ENTRY
;           VSF(DS:DX)
;               Path name address
;           VSF(CX)
;               Attributes
;
;       EXIT
;           SUCCESS
;               CY = 0
;               AX = assigned open handle
;           FAIL
;               CY = 1
;               AX = error code
;           HARD ERROR
;               CY = 1
;               AX = 0FFFFh
;
;       CONTEXT
;           Called from Virtual Mode
;           Executes in Kernel
;
;       STEPS
;           map pathname address
;           call create new file function
;
;       CALLS
;           demMapDSDX
;           w_3xCreateNew
;
;       USES
;           EAX,EBX,ECX,EDX,ESI,EDI,DS,ES
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING
        align  4

Procedure demCreateNew,near
        mov     ecx,[ebx].vsf_ecx
        call    demMapDSDX
        CALL16  w_3xCreateNew
        ret
EndProc   demCreateNew

;***LP  demCreateTemp - create a temporary file
;
;       ENTRY
;           VSF(DS:DX)
;               Path name address
;           VSF(CX)
;               Attributes
;
;       EXIT
;           SUCCESS
;               CY = 0
;               AX = Assigned Open Handle
;           FAIL
;               CY = 1
;               AX = error code
;           HARD ERROR
;               CY = 1
;               AX = 0FFFFh
;
;       CONTEXT
;           Called from Virtual Mode
;           Executes in Kernel
;
;       STEPS
;           map pathname address
;           call create temp file function
;
;       CALLS
;           demMapDSDX
;           w_CreateTempFile
;
;       USES
;           EAX,EBX,ECX,EDX,ESI,EDI,DS,ES
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING
        align  4

Procedure demCreateTemp,near
        mov     ecx,[ebx].vsf_ecx
        call    demMapDSDX
        CALL16  w_CreateTempFile
        ret
EndProc   demCreateTemp

;***LP  demDiskReset - Force Out All Pending Disk Writes
;
;       ENTRY
;           NONE
;
;       EXIT
;           NORMAL
;               NONE
;           HARD ERROR
;               AX = 0FFFFh
;
;       CONTEXT
;           Called from Virtual Mode
;           Executes in Kernel
;
;       STEPS
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;           w_DiskReset
;           NetFlushBuf
;
;       USES
;           EAX,ECX,EDX,ESI,EDI,ES
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING
        align  4

Procedure demDiskReset,near
        CALL16  w_DiskReset
        ASSUME  DS:NOTHING
        xor     ax,ax
        ret
EndProc   demDiskReset

SWAP32_22  segment    ;   wdm  merge 77963 and performance work
;***LP  demSetDefaultDrive - Set default disk drive
;
;       ENTRY
;           EBX
;               address of VSF
;            DL
;               drive number for new default drive
;
;       EXIT
;           SUCCESS
;               CY = 0
;               AL = count of drives
;               Current drive changed
;           FAILURE
;               CY = 1
;               AL = count of drives
;               Current drive not changed
;
;       CONTEXT
;           Called from Virtual Mode
;           Executes in Kernel
;
;       STEPS
;           CALL w_Set_Default_Drive
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;           w_Set_Default_Drive
;
;       USES
;           EAX,EBX,EDX
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING
        align  4

Procedure demSetDefaultDrive,near
        CALL16  w_Set_Default_Drive
        ret
EndProc   demSetDefaultDrive

;***LP  demSetDTA - Set Disk Transfer Area
;
;       ENTRY
;           VSF(DS):DX
;               Virtual Address of DTA
;
;       EXIT
;           Error not possible
;
;       CONTEXT
;           Called from Virtual Mode
;           Executes in Kernel
;
;       STEPS
;
;       NOTES
;           We re-use the selector from DTAddr, and simply re-map it
;           without changing it.  Only the offset of this pointer is
;           changed.  This selector is allocated when the VDM is
;           created.
;
;       WARNINGS
;           None
;
;       CALLS
;           demMapSegX
;
;       USES
;           EAX,ECX,EDX
;
        ASSUME  DS:FLAT,ES:FLAT,SS:TASKAREA,FS:NOTHING,GS:NOTHING
        align 4

Procedure demSetDTA,near
                                                ;72417 moved from PTDA to TCB
        push    bp
        mov     bp,ss:[CurrTCB]
        mov     ss:[bp].TCBDTAddr.Offst,dx      ; offset is the same as v86 mode
        pop     bp
                                                ;72417 end
        movzx   eax,[ebx].vsf_ds                ; get the segment       ;BC002;
        mov     edx,ISELDEMDTA
        call    demMapSegX                      ; map the sel to the segment
                                                ;72417 moved from PTDA to TCB
        push    bp
        mov     bp,ss:[CurrTCB]
        mov     ss:[bp].TCBDTAddr.Segmt,ax      ; store the new DTA selector
        pop     bp
                                                ;72417 end
        ret
EndProc   demSetDTA
SWAP32_22 ENDS


SWAP32_23 segment
;***LP  demRead - Read Handle
;
;       ENTRY
;           VSF(BX)
;               Handle (JFN) to Read (not fake handle)
;           VSF(CX)
;               Number of bytes to Read
;           VSF(DS):DX
;               Address of data buffer
;
;       EXIT
;           SUCCESS
;               CY = 0
;               AX = number of bytes written
;           FAIL
;               CY = 1
;               AX = error code
;           HARD ERROR
;               CY = 1
;               AX = 0FFFFh
;
;       CONTEXT
;           Called from Virtual Mode
;           Executes in Kernel
;
;       STEPS
;           Load address of read routine
;           JMP to demIO
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;           demDoIO/FSD_Read
;
;       USES
;           EAX,EBX,ECX,EDX,ESI,EDI,DS,ES
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING
        align   4

Procedure demRead,near
        mov     si,offset DOSHIGH2CODE:FSD_Read ; Regular old read
        jmp     demDoIO                 ; AX returned autmatically
EndProc   demRead

SWAP32_23 ENDS      ;  wdm merge 77963 and performance work


SWAP32_22  segment   ;  wdm merge 77963 and performance work
;***LP  demWrite - Write Handle
;***LP  demDoIO - Perform Read or Write Handle
;
;       ENTRY
;           VSF(BX)
;               Handle (JFN) (not fake handle)
;           VSF(CX)
;               Size of buffer, in bytes
;           VSF(DS):DX
;               Address of buffer
;           SI (demDoIO Only)
;               IO Entry point of filesystem (FSD_Read or FSD_Write)
;
;       EXIT
;           SUCCESS
;               CY = 0
;               AX = number of bytes written
;           FAIL
;               CY = 1
;               AX = error code
;           HARD ERROR
;               CY = 1
;               AX = 0FFFFh
;
;       CONTEXT
;           Called from Virtual Mode
;           Executes in Kernel
;
;       STEPS
;           Load address of OS/2 write routine
;
;           ENTRY demDoIO
;               Load registers from VSF
;               Call ReadDo to do IO
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;           demMapVirt
;           ReadDo/FSD_Write
;
;       USES
;           EAX,EBX,ECX,EDX,ESI,EDI,DS,ES
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING
        align 4

Procedure demWrite,near
        mov     si,offset DOSHIGH2CODE:FSD_Write ; INT 21 ver, CX=0 -> truncate

;       Enter here from demRead, too
;       (SI) = FSD_Read or FSD_Write

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

Entry   demDoIO,near,local
        bt      flVDMDEM,DEM_SLAVE_THREAD_BIT   ; if slave thread avail ;BN020;
        jc      short drw20                     ; send request to it    ;BN020;

        movzx   eax,[ebx].vsf_ds                ; (EAX) = base segment
        shl     eax,4                           ; (EAX) = linear base
        movzx   edx,dx                          ; (EDX) = offset
        add     eax,edx                         ; (EAX) = linear address
        movzx   ecx,[ebx].vsf_cx                ; (ECX) = transfer size
        xor     edx,edx                         ; (EDX) = selector index

vvideo_low      equ     000A0000h                                       ;BN015;
vvideo_high     equ     000C0000h-1                                     ;BN015;
vvideo_4K       equ     00001000h                                       ;BN015;
;EAX = linear address of read/write buffer                              ;BN015;
;ECX = size of read/write request                                       ;BN015;
        .if     <EAX be vvideo_high>                                    ;BN015;
          .if     <ECX ne 0>                                            ;BN016;
            ;------ the read/write is below to top of the video memory. ;BN015;
            push    ecx                                                 ;BN015;
            add     ecx,eax               ;ECX=high end of read/write   ;BN015;
            dec     ecx                   ;    buffer rounded to 4K     ;BN015;
            and     ecx,(-vvideo_4K)      ;    boundary.                ;BN015;
            .if     <ECX a vvideo_high>   ;are we above the video mem?  ;BN015;
              mov     ecx,vvideo_high+1-vvideo_4K ;ecx=top 4K in video  ;BN015;
            .endif                                                      ;BN015;
            .while  <ECX ae vvideo_low>   ;are we still in video memory?;BN015;
              cmp     byte ptr [ecx],0    ;touch FLAT:[ECX]             ;BN015;
              .leave  <EAX ae ECX>        ;are we at the bottom?        ;BN015;
              sub     ecx,vvideo_4K       ;step to the next lower 4K    ;BN015;
            .endwhile                                                   ;BN015;
            pop     ecx                                                 ;BN015;
          .endif                                                        ;BN016;
        .endif                                                          ;BN015;

        .errnz  ISELDEMTEMP
        call    demMapVirt                      ; (AX) = selector
        mov     ecx,[ebx].vsf_ecx               ; (CX) = transfer size
        mov     ebx,[ebx].vsf_ebx               ; (BX) = handle
        mov     ds,eax
        ASSUME  DS:NOTHING
        xor     edx,edx                         ; (DS:DX) = buffer address
        CALL16  ReadDo
        ret
drw20:                                                                  ;BN020;
        ASSUME  DS:FLAT                                                 ;BN020;
        xor     eax,eax                         ;                       ;BN020;
        mov     [ebx].vsf_ax,ax                 ; VSF(AX) == 0 for Read ;BN020;
        .if     <si eq <offset DOSHIGH2CODE:FSD_Write>> ; == 1 for Write;BN020;
          mov     [ebx].vsf_ax,1                ;                       ;BN020;
        .endif                                                          ;BN020;
        PCall   [pfnSlaveRequest] <ebx>         ; Send Request to Thread;BN020;
        ret                                                             ;BN020;
EndProc   demWrite
SWAP32_22  ENDS       ; wdm merge 77963 and performance work

SWAP32_22  segment    ; wdm merge 77963 and performance work

;***LP  demClose - Close Handle
;
;       Close the handle for the OS/2 file/device
;
;       ENTRY
;           VSF(BX)
;               Handle (JFN) to Close (not fake handle)
;
;       EXIT
;           SUCCESS
;               CY = 0
;               AX = # of opens (VJFN's) remaining on the handle
;               ZF = 0-->Still open under another VJFN
;                    1-->No opens remain
;               Handle successfully closed
;           FAIL
;               CY = 1
;               AX = system status code
;           HARD ERROR
;               CY = 1
;               AX = 0FFFFh
;
;       CONTEXT
;           Called from Virtual Mode
;           Executes in Kernel
;
;       STEPS
;           Get address of the JFN
;           Get ref_count of SF
;           call w_Close to close the handle
;           if rec_count was >=2
;
;       NOTES
;           Since demDup re-opens the SFT without allocating another
;           handle, we look at the SFT before closing to see if
;           it it multiply-opened.  If it is, we don't release the
;           JFN_Table entry (actually, we re-alloc after de-alloc).
;
;       WARNINGS
;           None
;
;       CALLS
;           pJFNFromHandle
;           SFFromSFN
;           w_Close
;
;       USES
;           EAX,EBX,ECX,EDX,ESI,EDI,DS,ES
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING
        align   4

Procedure demClose,near

LocalVar  pJFN,DWORD
LocalVar  SFN,WORD
LocalVar  cSFRef,WORD

        EnterProc
        mov     ebx,[ebx].vsf_ebx       ; BX = handle
        mov     eax,ebx                 ; Save for later
        CALL16  pJFNFromHandle          ; point to the JFN
        .if     nc                      ; bad handle?
          mov     pJFN.Segmt,es
          mov     pJFN.Offst,di
          mov     bx,es:[di]            ; Get the SFN
          mov     SFN,bx                ; Save it
          CALL16  SFFromSFN             ; es:di -> sft entry
          .if     nc                    ; valid SFN?
            mov     bx,es:[di].sf_ref_count ; Save ref.count.
            mov     cSFRef,bx
            mov     ebx,eax             ; Restore the handle
            call    dem_handle_Close
            push    eax                                                 ;58069;
            pushf                                                       ;58069;
;58069;     .if     nc                  ; Did the close succeed
            mov     ax,cSFRef
;58069;     sub     ax,1
            cmc                                                         ;58069;
            sbb     ax,0                                                ;58069;
            .if     a                 ; Skip if no more opens left
              LES     DI,pJFN
              mov     bx,SFN
              mov     es:[di],bx      ; Restore the handle
            .endif
            popf                                                        ;58069;
            pop     ecx                                                 ;58069;
            .if     c                                                   ;58069;
              mov     eax,ecx                                           ;58069;
            .endif
          .endif
        .endif
        LeaveProc
        ret
EndProc   demClose
SWAP32_22  ENDS        ;   wdm  merge 77963 and performance work
SWAP32_22  segment     ;   wdm  merge 77963 and performance work
Procedure dem_handle_Close,near
;Entry: BX=handle to close
;Exit:  CY,AX=error code
;       NC=ok
        xor     cx,cx                   ; fake filehandlelockID lowword  ;BN022
        xor     dx,dx                   ; fake filehandlelockID highword ;BN022
        CALL16  w_Close                 ; Perform the close
        ret
EndProc dem_handle_Close
SWAP32_22  ENDS        ;   wdm  merge 77963 and performance work

;***LP  demLockOper - Lock/Unlock file region
;
;       Lock/Unlock file region
;
;       ENTRY
;           VSF(BX)
;               Handle (JFN) to Close (not fake handle)
;           VSF(AX)
;               Lock Operation
;                   0 - lock region
;                   1 - unlock region
;           VSF(CX:DX)
;               start address of the region to be locked/unlocked
;           VSF(SI:DI)
;               length of the region to be locked/unlocked
;
;       EXIT
;           SUCCESS
;               CY = 0
;           FAIL
;               CY = 1
;               AX = system status code
;           HARD ERROR
;               CY = 1
;               AX = ERROR_INVALID_HANDLE
;                  = ERROR_INVALID_FUNCTION
;                  = ERROR_LOCK_VIOLATION
;
;       CONTEXT
;           Called from Virtual Mode
;           Executes in Kernel
;
;       STEPS
;           call w_LockOper
;
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;           w_LockOper
;
;       USES
;           ALL
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING
        align   4

Procedure demLockOper,near
        mov     ax,[ebx].vsf_ax                 ; operation type
        movzx   ecx,[ebx].vsf_cx                ; start offset
        movzx   edx,[ebx].vsf_dx
        movzx   esi,[ebx].vsf_si                ; length
        movzx   edi,[ebx].vsf_di
        movzx   ebx,[ebx].vsf_bx                ; BX = handle
        CALL16  w_LockOper
        ret
EndProc   demLockOper

SWAP32_23  segment      ;   wdm  merge 77963 and performance work
;***LP  demChgFilePtr - Change file read/write location pointer
;
;       Change OS/2 file read/write location pointer
;
;       ENTRY
;           VSF(BX)
;               Handle (JFN) of file to reposition (not fake handle)
;           VSF(CX:DX)
;               32-bit location specification (depends on AL)
;           AL
;               Positioning method
;                   0 - File Absolute
;                   1 - Relative to Current Position
;                   2 - Relative to End of File
;
;       EXIT
;           SUCCESS
;               Position changed
;               CY = 0
;               VSF(DX):AX = 32-bit File-absolute read/write position
;           FAIL
;               CY = 1
;               AX = error code
;           HARD ERROR
;               CY = 1
;               AX = 0FFFFh
;
;       CONTEXT
;           Called from Virtual Mode
;           Executes in Kernel
;
;       STEPS
;           Set up registers
;           Call w_LSeek
;           if error == ERROR_SEEK_ON_DEVICE
;               DX:AX = 0:0
;               clear error condition
;           return DX register
;
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;           w_LSeek
;
;       USES
;           EAX,ECX,EDX,ESI,EDI,ES
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING
        align   4

Procedure demChgFilePtr,near
        push    ebx                     ; Save pointer to VSF
        xor     ah,ah                   ; AX = method
        mov     edx,[ebx].vsf_edx       ; Get low offset
        mov     ecx,[ebx].vsf_ecx       ; Get hi offset
        mov     ebx,[ebx].vsf_ebx       ; Get handle
        xor     di,di                   ; fake filehandlelockID lowword ; BN022
        xor     si,si                   ; fake filehandlelockID highword; BN022
        CALL16  w_LSeek
        assume  ds:NOTHING
        .if     c                       ; Skip if no error
          cmp     ax,ERROR_SEEK_ON_DEVICE ; Allowed for DOS
          stc
          .if     z                     ; Skip if a different error
            xor     ax,ax               ; Clear error condition
            mov     dx,ax               ; return new location as 0:0
          .endif
        .endif
        pop     ebx
        FlatContext <ds>
        mov     [ebx].vsf_dx,dx         ; Return DX
        ret                             ; AX returned on the way out
EndProc   demChgFilePtr
SWAP32_23 ENDS                 ;  wdm merge 77963 and performance work

SWAP32_25  segment
;***LP  demFileTimes - Query/Set File Modified Time and Date
;
;       Query/Set File Modified Time and Date
;
;       GET TIME (AL = 0)
;
;           ENTRY
;               VSF(BX)
;                   Handle (JFN) of file to query (not fake handle)
;
;           EXIT
;               SUCCESS
;                   CF = 0
;                   VSF(CX) = File time
;                   VSF(DX) = File date
;               FAILURE
;                   CF = 1
;                   AX = error code
;
;       SET TIME (AL = 1)
;
;           ENTRY
;               VSF(BX)
;                   Handle (JFN) of file on which to modify time
;               VSF(CX)
;                   New file time
;               VSF(DX)
;                   New file date
;
;           EXIT
;               SUCCESS
;                   CF = 0
;               FAILURE
;                   CF = 1
;                   AX = error code
;
;       HARD ERROR EXIT
;           CF = 1
;           AX = 0FFFFh
;
;       CONTEXT
;           Called from Virtual Mode
;           Executes in Kernel
;
;       STEPS
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;
;       USES
;           EAX,ECX,EDX,ESI,EDI,ES
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING
        align   4

Procedure demFileTimes,near

dft_max_name equ 260
LocalVar  dft_AsciizName,dft_max_name
LocalVar  dft_ArgFrame,<size Open3Struc>        ; frame to pass to w_OpenCreate
;opn3s_Reserved   dd ?             ; reserved dword
;opn3s_FileHandleLockIDPtr dd 0    ; Pointer to FileHandleLockID buffer
;opn3s_EABufPtr   dd 0             ; Pointer to EA buffer
;opn3s_Mode       dw vsf(bx)       ; Open mode for file
;opn3s_Mode2      dw 0             ; high word of OpenMode
;opn3s_Flag       dw vsf(dx)       ; Flags for open
;opn3s_Attrs      dw vsf(cx)       ; File attribute
;opn3s_Size       dd 0             ; Size of file
;opn3s_ActionPtr  dd ?             ; Pointer to location for returned action
;opn3s_HandlePtr  dd ?             ; Pointer to location for returned handle
;opn3s_NamePtr    dd *vsf(ds:si)   ; Pointer to file name

        EnterProc

        push    ebx                     ; save pointer to VSF
        mov     edx,[ebx].vsf_edx       ; get date
        mov     ecx,[ebx].vsf_ecx       ; get time
        mov     ebx,[ebx].vsf_ebx       ; get handle
        CALL16  FileTimes
        ASSUME  DS:NOTHING
        pop     ebx
        FlatContext <ds>
        .if     nc
          .if     <<[ebx].vsf_al> eq 0> ; skip if time was set
            mov     [ebx].vsf_dx,dx     ; return date
            mov     [ebx].vsf_cx,cx     ; return time
          .endif
          clc
        .else near
          push    eax
          .if     <<[ebx].vsf_al> eq 1> near
public DemTouchHack
DemTouchHack:
            push    ebx
            ;Did we fail due to read only handle?
            mov     ebx,[ebx].vsf_ebx
            CALL16  SFFromHandle        ; get the SF entry
            pop     ebx
            assume  es:nothing  ;es=SFT segment
            mov     al,byte ptr es:[di].sf_fsi.sfi_mode
            .if     <BIT al nand 0Fh> near  ;only for access=Read-only
              or      al,80h    ;=force the NoInherit bit on
              mov     dl,02     ;=default new open to R/W mode
              .if     <al eq 0B0h>  ;if 1st handle is DenyRead then open W/O
                mov     dl,01
              .endif
              or      al,dl
              xor     ah,ah
              mov     dft_ArgFrame.opn3s_Mode,ax
              push    ebx
              mov     eax,es:[di].sf_MFT
              lea     esi,[eax].mft_name
              lea     edi,[dft_AsciizName]
              push    ss
              pop     es
              assume  es:nothing  ;es=stack
              mov     dft_ArgFrame.opn3s_NamePtr.Offst,di
              mov     dft_ArgFrame.opn3s_NamePtr.Segmt,es
              cld
              mov     cx,dft_max_name
              .repeat
                lodsb
                stosb
                dec     cx
                .if     nz
                  or      al,al
                .endif
              .until  z
              xor     eax,eax
              mov     dft_ArgFrame.opn3s_FileHandleLockIDPtr,eax
              mov     dft_ArgFrame.opn3s_EABufPtr,eax
              mov     dft_ArgFrame.opn3s_Size,eax
              mov     dft_ArgFrame.opn3s_Mode2,ax
              mov     dft_ArgFrame.opn3s_Attrs,ax
              inc     eax
              mov     dft_ArgFrame.opn3s_Flag,ax  ;not exist=fail, exist=open
              mov     ah,attr_hidden+attr_system+attr_directory ; AH = Sattrib
              mov     al,OPCR_SATTR_INDIRECT    ; AL=1, call SetAttrib to set
                                                ;       Sattrib
              lea     bx,[dft_ArgFrame]         ; SS:BX = &Argument frame
              mov     dl,IFaceLevel3            ; DL = DosOpen2Compt IFaceLevel

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

              CALL16  w_OpenCreate
              FlatContext <ds>
              pop     ebx
              .if     nc
                mov     edx,[ebx].vsf_edx       ; get date
                mov     ecx,[ebx].vsf_ecx       ; get time
                mov     ebx,eax
                push    ebx                                             ;60303;
                CALL16  FileTimes
                pop     ebx                                             ;60303;
                .if     nc
                  pop     edx           ;throw away old return
                  push    eax           ;save new return instead
                  call    dem_handle_Close
                  clc
                  jmp     short demTouchDone
                .endif
                call    dem_handle_Close
              .endif
            .endif
          .endif
          stc
demTouchDone:
          pop     eax
        .endif
        LeaveProc
        ret                             ; AX returned on the way back
EndProc   demFileTimes
SWAP32_25 ENDS

SWAP32_28  segment
;***LP  demExtInfo - Query/Set Extended Attribute Information
;
;       Query/Set File Extended Attribute Information
;
;       ENTRY
;           GET INFO (AL = 2)
;           SET INFO (AL = 3)
;
;           VSF(BX)
;               Handle (JFN) of file to query (not fake handle)
;
;       EXIT
;           SUCCESS
;               CF = 0
;               EA's returned or updated
;           FAILURE
;               CF = 1
;               AX = error code
;
;       HARD ERROR EXIT
;           CF = 1
;           AX = 0FFFFh
;
;       CONTEXT
;           Called from Virtual Mode
;           Executes in Kernel
;
;       STEPS
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;           demMapESDI
;           demMapDS
;           Ext_Information
;
;       USES
;           EAX,EBX,ECX,EDX,ESI,EDI,EBP,DS,ES
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING
        align   4

Procedure demExtInfo,near
        mov     ecx,[ebx].vsf_ecx
        mov     edx,[ebx].vsf_edx
        call    demMapESDI
        ASSUME  ES:NOTHING
        mov     esi,[ebx].vsf_esi
        push    [ebx].vsf_ebx
        call    demMapDS
        ASSUME  DS:NOTHING
        pop     ebx
        CALL16  Ext_Information
        ret
EndProc   demExtInfo
SWAP32_28  ends

SWAP32_28  segment
;***LP  demFindFirstFCB - FCB-style find-first directory entry
;
;       FCB-style find-first directory entry
;
;       ENTRY
;           VSF(DS:DX)
;               Address of the search FCB (unopened)
;
;       EXIT
;           SUCCESS
;               CF = 0
;               AX = ?
;           FAILURE
;               CF = 1
;               AX = error code
;
;       HARD ERROR EXIT
;           CF = 1
;           AX = 0FFFFh
;
;       CONTEXT
;           Called from Virtual Mode
;           Executes in Kernel
;
;       STEPS
;           Get registers from frame
;           call Dir_Search_First
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;           demMapDSDX
;           Dir_Search_First
;
;       USES
;           EAX,EBX,ECX,EDX,ESI,EDI,ES,DS
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING
        align   4

Procedure demFindFirstFCB,near
LocalVar dummycds,<SIZE curdir>
LocalVar openbuf,PMPATHLEN
LocalVar dummy,WORD                     ; KLUDGE: see gshare.asm
LocalVar searchbuf,SRCHBUFSIZE+1
        EnterProc

        push    ebx
        mov     ebx,[_pTCBCur]           ;### PTR B720732
        lea     dx,dummycds
        mov     [ebx].TCBpTmpCDS.Offst,dx      ; Initialize ptda_pCDS ;### PTR B720732
        lea     dx,searchbuf
                                              ;72417 moved from PTDA to TCB
        mov     [ebx].TCB_pSrchBuf,dx         ; Initialize TCB_pSrchBuf
                                              ;72417 end
        lea     dx,openbuf
        mov     [ebx].TCBpOpenBuf,dx          ; Initialize ptda_pOpenBuf
        pop     ebx

        call    demMapDSDX
        ASSUME  DS:NOTHING

        CALL16  Dir_Search_First
                                          ;72417 moved from PTDA to TCB
        push    bp
        mov     bp,ss:[CurrTCB]
        mov     ss:[bp].TCB_pSrchBuf,0    ; Clear ptda_pSrchBuf
        pop     bp
                                          ;72417 end
        LeaveProc
        ret
EndProc   demFindFirstFCB
SWAP32_28  ends

;***LP  demFindNextFCB - FCB-style find-Next directory entry
;
;       FCB-style find-Next directory entry
;
;       ENTRY
;           VSF(DS:DX)
;               Address of the search FCB (set up from call to FindFirstFCB)
;
;       EXIT
;           SUCCESS
;               CF = 0
;               AX = ?
;           FAILURE
;               CF = 1
;               AX = error code
;
;       HARD ERROR EXIT
;           CF = 1
;           AX = 0FFFFh
;
;       CONTEXT
;           Called from Virtual Mode
;           Executes in Kernel
;
;       STEPS
;           Get registers from frame
;           call Dir_Search_Next
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;           demMapDSDX
;           Dir_Search_Next
;
;       USES
;           EAX,EBX,ECX,EDX,ESI,EDI,ES,DS
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING
        align   4

Procedure demFindNextFCB,near
LocalVar dummycds,<SIZE curdir>
LocalVar openbuf,PMPATHLEN
LocalVar dummy,WORD                     ; KLUDGE: see gshare.asm
LocalVar searchbuf,SRCHBUFSIZE+1
        EnterProc

        push    ebx
        mov     ebx,[_pTCBCur]           ;### PTR B720732
        lea     dx,dummycds
        mov     [ebx].TCBpTmpCDS.Offst,dx      ; Initialize ptda_pCDS ;### PTR B720732
        lea     dx,searchbuf
                                              ;72417 moved from PTDA to TCB
        mov     [ebx].TCB_pSrchBuf,dx         ; Initialize TCB_pSrchBuf
                                              ;72417 end
        lea     dx,openbuf
        mov     [ebx].TCBpOpenBuf,dx          ; Initialize ptda_pOpenBuf
        pop     ebx

        call    demMapDSDX
        ASSUME  DS:NOTHING
        CALL16  Dir_Search_Next

                                              ;72417 moved from PTDA to TCB
        push    bp
        mov     bp,ss:[CurrTCB]
        mov     ss:[bp].TCB_pSrchBuf,0        ; Clear TCB_pSrchBuf
        pop     bp
                                              ;72417 end

        LeaveProc
        ret
EndProc   demFindNextFCB

SWAP32_28  segment
;***LP  demGetDriveFreespace - Get drive free space
;
;       Get allocation size/freespace information
;
;       ENTRY
;               DL = drive number
;
;       EXIT
;           SUCCESS
;               CF = 0
;               AL = FAT ID byte
;               VSF(BX) = Number of free allocation units
;               VSF(CX) = Sector size
;               VSF(DX) = Total Number of allocation units on disk
;               VSF(SI) = Sectors per allocation unit
;
;           FAILURE
;               CF = 1
;               AX = Error code
;
;       CONTEXT
;           Called from Virtual Mode
;           Executes in Kernel
;
;       USES
;           EAX,ECX,EBX,EDX,EBP,ESI,EDI,DS,ES
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING

Procedure demGetDriveFreespace,near
        push    ebx                     ; save pvsf
        CALL16  w_Get_Drive_Freespace   ; call the filesystem
        pop     esi                     ; (ESI) = pvsf
        .if     nc                      ; exit if error
          FlatContext <ds>,edi
          mov     [esi].vsf_bx,bx       ; save return parameters
          mov     [esi].vsf_cx,cx
          mov     [esi].vsf_dx,dx
          mov     [esi].vsf_si,ax

;         Find out FSC; if FAT, get media byte in AH; for other FSD's
;         return 0f0h in AH - to mean anything other than the std. set
;         of recognised media such as dsdd,dssd 5 1/4 disks etc.

          mov     esi,[_pTCBCur]        ; (ESI) = pointer to TCB
          mov     bp,[esi].TCBThishVPB
          VPBContext es,bp,nocheck      ; (ES:BP) = vpb pointer
          mov     di,FSD_MEDIA_BYTE     ; (DI) = preload media byte for FSDs
          .if     <<es:[bp].vpb_FSC.Offst> eq FSC_LOCAL>
                                        ; if FAT, go get media byte

            ; FAT mounted volume; get the media byte.  FAT by default
            ; is also treated like an FSD since we don't really know
            ; the media type.  (FAT-by-default is recognised by
            ; vpdFAT_FAT_count being zero.)

            .if     <<es:[bp].vpb_fsd.vpdFAT_FAT_count> ne 0>
              TaskContext <ds>,ax         ; jump if FAT-by-default
              xor     ebx,ebx
              CALL16  UnPack              ; (DI) = media byte
            .endif
          .endif
          mov     ax,di                 ; (AL) = media byte
          clc
        .endif
        ret
EndProc   demGetDriveFreespace
SWAP32_28  ends


SWAP32_25  segment           ;   wdm merge 77963 and performance work
;---------------------------------------------------------------------- ;BN013;
                                                                        ;BN013;
;***LP  demFindFirst - Path-style find first directory entry            ;BN013;
;                                                                       ;BN013;
;       Path-style find-first directory entry                           ;BN013;
;                                                                       ;BN013;
;       ENTRY                                                           ;BN013;
;           VSF(DS:DX)                                                  ;BN013;
;               Address of the pathname with wildcards                  ;BN013;
;           VSF(CX)                                                     ;BN013;
;               Attribute to match                                      ;BN013;
;           [DTA]                                                       ;BN013;
;               search structure buffer                                 ;BN013;
;                                                                       ;BN013;
;       EXIT                                                            ;BN013;
;           SUCCESS                                                     ;BN013;
;               CF = 0                                                  ;BN013;
;               [DTA] search structure updated                          ;BN013;
;           FAILURE                                                     ;BN013;
;               CF = 1                                                  ;BN013;
;               AX = error code                                         ;BN013;
;                                                                       ;BN013;
;       HARD ERROR EXIT                                                 ;BN013;
;           CF = 1                                                      ;BN013;
;           AX = 0FFFFh                                                 ;BN013;
;                                                                       ;BN013;
;       CONTEXT                                                         ;BN013;
;           Called from Virtual Mode                                    ;BN013;
;           Executes in Kernel                                          ;BN013;
;                                                                       ;BN013;
;       STEPS                                                           ;BN013;
;           Get registers from frame                                    ;BN013;
;           call w_3xFindFirst                                          ;BN013;
;                                                                       ;BN013;
;       NOTES                                                           ;BN013;
;           None                                                        ;BN013;
;                                                                       ;BN013;
;       WARNINGS                                                        ;BN013;
;           None                                                        ;BN013;
;                                                                       ;BN013;
;       CALLS                                                           ;BN013;
;           demMapDSDX                                                  ;BN013;
;           w_3xFindFirst                                               ;BN013;
;                                                                       ;BN013;
;       USES                                                            ;BN013;
;           EAX,EBX,ECX,EDX,ESI,EDI,EBP,ES,DS                           ;BN013;
;                                                                       ;BN013;
;                                                                       ;BN013;
;***LP  demFindNext - Path-style find next directory entry              ;BN013;
;                                                                       ;BN013;
;       ENTRY                                                           ;BN013;
;           [DTA] = search structure                                    ;BN013;
;                                                                       ;BN013;
;       EXIT                                                            ;BN013;
;           SUCCESS                                                     ;BN013;
;               CF = 0                                                  ;BN013;
;               [DTA] updated                                           ;BN013;
;           FAILURE                                                     ;BN013;
;               CF = 1                                                  ;BN013;
;               AX = error code                                         ;BN013;
;                                                                       ;BN013;
                                                                        ;BN013;
dff_asciiz_max  equ     128                                             ;BN013;
FindFirstHackEntry struc                                                ;BN013;
dff_next_entry     dd   ?                                               ;BN013;
dff_last_entry     dd   ?                                               ;BN013;
dff_saved_attr     dd   ?                                               ;BN013;
dff_save_asciiz    db   dff_asciiz_max dup (?)                          ;BN013;
FindFirstHackEntry ends                                                 ;BN013;
                                                                        ;BN013;
                                                                        ;BN013;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING        ;BN013;
        align   4                                                       ;BN013;
Procedure demFindFirst,near                                             ;BN013;
LocalVar dff_allocate,DWORD                                             ;BN013;
LocalVar dff_temp_string,<dff_asciiz_max>                               ;BN013;
        EnterProc                                                       ;BN013;
                                                                        ;BN013;
;------ initialize local variable flag                                  ;BN013;
        mov     dff_allocate,0                                          ;BN013;
                                                                        ;BN013;
;------ get user values CX and DS:DX                                    ;BN013;
        movzx   ecx,[ebx].vsf_cx                                        ;BN013;
        call    demMapDSDX                                              ;BN013;
        assume  ds:NOTHING                                              ;BN013;
                                                                        ;BN013;
;------ Is the volume label bit on?  If yes, then we have work to do.   ;BN013;
        .if     <BIT CL and 8>                                          ;BN013;
          ;code below AND code in src\dos\filesys\search.asm            ;120690
          ;(w_3xFindFirst) depend upon the cld instruction below        ;120690
          cld                                                           ;BN013;
                                                                        ;BN013;
          ;------ Are any other bits other than volume label on?        ;BN013;
          .if     <BIT CL and <NOT 8>>                                  ;BN013;
                                                                        ;BN013;
            ;------ Yes, label and other bits are on... it's hack time! ;BN013;
            call    dem_FFHack                                          ;BN013;
            ;returns: eax=buffer address and cx=new attributes          ;BN013;
            mov     dff_allocate,eax                                    ;BN013;
                                                                        ;BN013;
          .endif                                                        ;BN013;
                                                                        ;BN013;
          ;------ fix for our File System unable to handle "." in label ;BN013;
          .if     <BIT CL and 8>                                        ;BN013;
                                                                        ;BN013;
;120690;*******  B E G I N  commented out code for defect 120690  ******;120690;
;120690;----------------------------------------------------------------;120690;
;120690;            ;------ copy asciiz DS:DX to temp storage (dff_temp_String) ;BN013;
;120690;            push    es                                                  ;BN013;
;120690;            movzx   esi,dx              ; load DS:ESI with ptr to path  ;BN013;
;120690;            push    ss                  ; load ES:EDI with ptr to temp  ;BN013;
;120690;            pop     es                                                  ;BN013;
;120690;            assume  es:nothing                                          ;BN013;
;120690;            lea     edi,dff_temp_string                                 ;BN013;
;120690;            mov     edx,edi             ; save start of string          ;BN013;
;120690;            mov     ah,dff_asciiz_max   ; init counter                  ;BN013;
;120690;            .repeat                     ; copy string to our buffer     ;BN013;
;120690;              lodsb                                                     ;BN013;
;120690;              .if     <al ne '.'>       ; if dot don't copy char        ;BN013;
;120690;                stosb                   ; else copy char to our buffer  ;BN013;
;120690;              .endif                                                    ;BN013;
;120690;              dec     ah                                                ;BN013;
;120690;            .until  z or                ; copy up to 128 chars          ;BN013;
;120690;            .until  <AL eq 0>                                           ;BN013;
;120690;                                                                        ;BN013;
;120690;            ;------ DS:DX = &dff_temp_string (new temporary string)     ;BN013;
;120690;            push    es                  ;load DS:DX with ptr to new path;BN013;
;120690;            pop     ds                  ;DX was assigned above          ;BN013;
;120690;            pop     es                  ;restore ES value               ;BN013;
;120690;            assume  ES:FLAT                                             ;BN013;
;120690;                                                                        ;BN013;
;120690;            ;------ if AL is not 0, then our asciiz is illegal, too long;BN013;
;120690;            .if     <AL ne 0>                                           ;BN013;
;120690;***********  E N D commented out code for defect 120690  *******;120690;
;120690;----------------------------------------------------------------;120690;
                                                                        ;120690;
             ; If vol label spec is greter than dff_asciiz_max chars    ;120690;
             ; long, indicate error condition (dos compatibility)       ;120690;
             push    es                                                 ;120690;
             push    ds                                                 ;120690;
             pop     es                                                 ;120690;
             assume  es:nothing                                         ;120690;
             movzx   edi,dx              ;es:edi->filespec (for scasb)  ;120690;
             xor     ax,ax               ;search for null terminator    ;120690;
             push    cx                                                 ;120690;
             mov     cx,dff_asciiz_max   ;max search length             ;120690;
             repnz   scasb               ;search up to dff_asciiz_max   ;120690;
             pop     cx                  ; chars for null terminator    ;120690;
             pop     es                                                 ;120690;
             assume  ES:FLAT                                            ;120690;
                                                                        ;120690;
      ; -- if nz then the null terminator was not found before checking ;120690;
      ; -- dff_asciiz_max # of chars => file spec is illegal (too long).;120690;
            .if nz                                                      ;120690;
              stc                                                       ;BN013;
              mov     eax,1      ;invalid function                      ;BN013;
              jmp     short dff_2ndpass                                 ;BN013;
            .endif                                                      ;BN013;
                                                                        ;BN013;
          .endif                                                        ;BN013;
                                                                        ;BN013;
        .endif                                                          ;BN013;
                                                                        ;BN013;
                                                                        ;BN013;
;------ perform the "find first"                                        ;BN013;
dff_try_again:                                                          ;BN013;
        assume  ds:nothing,ES:FLAT                                      ;BN013;
        CALL16  w_3xFindFirst                                           ;BN013;
        assume  ds:nothing,es:nothing   ;this worker kill DS and ES     ;BN013;
                                                                        ;BN013;
        jmp     short dff_2ndpass                                       ;BN013;
                                                                        ;BN013;
                                                                        ;BN013;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING        ;BN013;
        align   4                                                       ;BN013;
Entry   demFindNext                                                     ;BN013;
        EnterProc ,NoCheck                                              ;BN013;
;------ Get the special flag from the DTA                               ;BN013;
        xor     esi,esi                                                 ;BN013;
                                              ;72417 moved from PTDA to TCB
        push    bp
        mov     bp,ss:[CurrTCB]
        LDS     SI,ss:[bp].TCBDTAddr                                    ;BN013;
        pop     bp
                                              ;72417 end
        assume  ds:nothing                                              ;BN013;
        mov     eax,ds:[esi].dem_FF_buffer                              ;BN013;
        mov     dff_allocate,eax                                        ;BN013;
                                                                        ;BN013;
;------ Check for Rewind/FastForward change in DOS_LastEnt              ;BN021;
;;;;;;; mov     ax,ds:[esi].DOS_LastEnt                                 ;BN021;
;;;;;;; .if     <AX b <ds:[esi].OS2_LastEnt>>                           ;BN021;
;;;;;;;   ;//rewind                                                     ;BN021;
;;;;;;; .else                                                           ;BN021;
;;;;;;;   ;//fast forward or normal                                     ;BN021;
;;;;;;; .endif                                                          ;BN021;
                                                                        ;BN021;
;------ Perform the "find next"                                         ;BN021;
;;;;;;; .repeat                                                         ;BN021;
          CALL16  w_3xFindNext                                          ;BN021;
;;;;;;; .until  c or                                                    ;BN021;
;;;;;;; .until  <newLastEnt >= oldDosLastEnd>                           ;BN021;
                                                                        ;BN013;
                                                                        ;BN013;
PUBLIC  dff_2ndpass                                                     ;BN013;
dff_2ndpass:                                                            ;BN013;
        assume  ds:nothing,es:nothing                                   ;BN013;
                                                                        ;BN013;
        mov     ecx,dff_allocate                                        ;BN013;
        .if     nc                                                      ;BN013;
                                                                        ;BN021;
          ;------ Operation success, save information in the DTA        ;BN021;
          mov     esi,0                                                 ;BN013;
                                              ;72417 moved from PTDA to TCB
          push    bp
          mov     bp,ss:[CurrTCB]
          LDS     SI,ss:[bp].TCBDTAddr                                  ;BN013;
          pop     bp
                                              ;72417 end
          assume  ds:nothing                                            ;BN013;
                                                                        ;BN013;
          ;------ DTA.DOS_LastEnt := DTA.OS2_LastEnt                    ;BN013;
          push    ds:[esi].OS2_LastEnt                                  ;BN013;
          pop     ds:[esi].DOS_LastEnt                                  ;BN013;
                                                                        ;BN013;
          ;------ save the special flag state for FindNext              ;BN013;
          mov     ds:[esi].dem_FF_buffer,ecx                            ;BN013;
                                                                        ;BN013;
        .else                                                           ;BN013;
                                                                        ;BN013;
          ;------ Operation failure, see if a "hack" record exists.     ;BN021;
          .if     ncxz                                                  ;BN013;
                                                                        ;BN013;
            ;------ see if "hack" record is valid.                      ;BN021;
            FlatContext <ds>,esi                                        ;BN017;
            assume  DS:FLAT                                             ;BN013;
            push    ss                                                  ;BN013;
            pop     es                                                  ;BN013;
            assume  DS:FLAT,es:nothing                                  ;BN013;
            cld                                                         ;BN017;
            mov     esi,[_demFindFirstHack_head]                        ;BN017;
            .while  <esi ne 0> and                                      ;BN017;
            .while  <esi ne ecx>                                        ;BN017;
              mov     esi,ds:[esi].dff_next_entry                       ;BN017;
            .endwhile                                                   ;BN017;
                                                                        ;BN013;
            .if     <esi ne 0>          ;ds:esi=&saved info.            ;BN017;
                                                                        ;BN021;
              ;------ we have a valid "hack" record                     ;BN021;
                                                                        ;BN021;
              ;------ get the saved values                              ;BN021;
              add     esi,dff_saved_attr                                ;BN017;
              lodsd                       ;eax=attribute                ;BN013;
              lea     edi,dff_temp_string ;es:edi = &temp               ;BN013;
              mov     edx,edi                                           ;BN013;
              mov     ecx,dff_asciiz_max/4                              ;BN013;
              .errnz (dff_save_asciiz - dff_saved_attr - 4)             ;BN017;
              rep     movsd                                             ;BN013;
              ;------ save new find first values                        ;BN013;
              push    es                                                ;BN013;
              push    eax                                               ;BN013;
              push    edx                                               ;BN013;
              ;------ deallocate temporary buffer                       ;BN013;
              push    ds                                                ;BN013;
              pop     es                                                ;BN013;
              assume  DS:FLAT,ES:FLAT                                   ;BN013;
              xor     esi,esi                                           ;BN013;
              xchg    dff_allocate,esi                                  ;BN013;
              mov     edi,[esi].dff_next_entry                          ;BN013;
              push    [esi].dff_last_entry                              ;BN013;
              .if     <ESI eq [_demFindFirstHack_head]>                 ;BN013;
                mov     [_demFindFirstHack_head],edi                    ;BN013;
              .endif                                                    ;BN013;
              CCALL32 _VMFreeKHB <VM_HKH_PUB_SWAPRW, esi>               ;BN013;
              pop     esi                                               ;BN013;
              .if     <ESI ne 0>                                        ;BN013;
                mov     [esi].dff_next_entry,edi                        ;BN013;
              .endif                                                    ;BN013;
              .if     <EDI ne 0>                                        ;BN013;
                mov     [edi].dff_last_entry,esi                        ;BN013;
              .endif                                                    ;BN013;
              ;------ restore new find first values                     ;BN013;
              pop     edx                                               ;BN013;
              pop     ecx                                               ;BN013;
              pop     ds                                                ;BN013;
              jmp     dff_try_again                                     ;BN013;
                                                                        ;BN013;
            .endif                                                      ;BN013;
            stc                                                         ;BN017;
          .endif                                                        ;BN013;
        .endif                                                          ;BN013;
                                                                        ;BN013;
        LeaveProc                                                       ;BN013;
        ret                                                             ;BN013;
EndProc   demFindFirst                                                  ;BN013;
SWAP32_25 ENDS          ;   wdm merge 77963 and performance work
;---------------------------------------------------------------------- ;BN013;
        page                                                            ;BN013;
;                                                                       ;BN013;
; "dem_FFHack"                                                          ;BN013;
;                                                                       ;BN013;
; This procedure is called by the Find First if the volume label and    ;BN013;
; any other attribute bits are on.  The OS/2 File System is not able    ;BN013;
; to handle this condition, so this "hack" is in place to correct the   ;BN013;
; situation.  This procedure will attempt to allocate a buffer and      ;BN013;
; save the asciiz and attribute information alway for a 2nd pass        ;BN013;
; through FindFirst.  The first pass will handle the volume label bit   ;BN013;
; only.  The second pass will handle all other bits.  If the buffer     ;BN013;
; allocation fails, the default is to ignore the volume label bit.      ;BN013;
;                                                                       ;BN013;
;                                                                       ;BN013;
;Entry: cx    == find first attribute                                   ;BN013;
;       ds:dx == asciiz                                                 ;BN013;
;Exit:  eax   == dff_allocate value=temporary buffer address            ;BN013;
;       cx    == find first attribute                                   ;BN013;
;       ds:dx == asciiz                                                 ;BN013;
;                                                                       ;BN013;
                                                                        ;BN013;
        align   4                                                       ;BN013;
        ASSUME  DS:nothing,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING     ;BN013;
                                                                        ;BN013;
Procedure dem_FFHack,near                                               ;BN013;
                                                                        ;BN013;
;------ save registers                                                  ;BN013;
        push    es                                                      ;BN013;
        push    ds                                                      ;BN013;
        push    edx                                                     ;BN013;
        push    ecx                                                     ;BN013;
                                                                        ;BN013;
;------ allocate swappable heap buffer space                            ;BN013;
        ;rc = VMAllocKHB(hkh, cb, hobOwner, fl, ppbData)                ;BN013;
        ;VM_HKH_PUB_SWAPRW = heap header handle (equ vmexport)          ;BN013;
        ;132               = size of request in bytes                   ;BN013;
        ;hobOwner          = owner of heap block                        ;BN013;
        ;0                 = flags for the request                      ;BN013;
        ;save              = &vmkhbi, heap block info                   ;BN013;
        ;return int EAX                                                 ;BN013;
        ;                                                               ;BN013;
        push    es                                                      ;BN013;
        pop     ds                                                      ;BN013;
        assume  DS:FLAT                                                 ;BN013;
        movzx   eax,ss:[ptda_handle]    ;ptda_handle is word sized      ;BN013;
        lea     edi,_demAllocBlkVMKHBI                                  ;BN013;
        CCALL32 _VMAllocKHB <VM_HKH_PUB_SWAPRW, \
                             <(SIZE FindFirstHackEntry)>, \
                             eax, \
                             0, \
                             edi>
        .if     <eax eq 0>      ;if alloc suceeds, then eax:=buffer address
          mov     eax,[_demAllocBlkVMKHBI].khbi_pbData                  ;BN013;
        .else                                                           ;BN013;
          xor     eax,eax       ;if alloc fails, then eax:=0            ;BN013;
        .endif                                                          ;BN013;
                                                                        ;BN013;
;------ restore registers                                               ;BN013;
        pop     ecx                                                     ;BN013;
        pop     edx                                                     ;BN013;
        pop     ds                                                      ;BN013;
        pop     es                                                      ;BN013;
                                                                        ;BN013;
;------ default is to do a non-volume label operation                   ;BN013;
        and     CL,NOT 8            ;get rid of the label bit           ;BN013;
                                                                        ;BN013;
;------ Did the allocate succeed                                        ;BN013;
        .if     <eax ne 0>          ;if (alloc_flag==TRUE) then:        ;BN013;
                                                                        ;BN013;
          ;------ addressability and increment string OpCodes           ;BN013;
          mov     edi,eax               ;es:edi=&buffer                 ;BN013;
                                                                        ;BN013;
          ;------ Save the buffer address of clean-up later             ;BN013;
          xchg    eax,es:[_demFindFirstHack_head]                       ;BN013;
                                                                        ;BN013;
          ;------ Save the tail info in the last entry                  ;BN013;
          .if     <EAX ne 0>                                            ;BN013;
            mov     es:[eax].dff_last_entry,edi                         ;BN013;
          .endif                                                        ;BN013;
                                                                        ;BN013;
          ;------ Save info away for future 2nd pass (non-label pass)   ;BN013;
          stosd                         ;next entry                     ;BN013;
          xor     eax,eax                                               ;BN013;
          .errnz (dff_last_entry - dff_next_entry - 4)                  ;BN017;
          stosd                         ;last entry                     ;BN013;
          mov     eax,ecx               ;the label bit was removed above;BN013;
          .errnz (dff_saved_attr - dff_last_entry - 4)                  ;BN017;
          stosd                         ;save the 2nd pass attribute    ;BN013;
          xor     esi,esi                                               ;BN013;
          mov     si,dx                 ;ds:esi=asciiz                  ;BN013;
          mov     cx,dff_asciiz_max                                     ;BN013;
          .errnz (dff_save_asciiz - dff_saved_attr - 4)                 ;BN017;
          ;------ move one byte at a time until end of asciiz found     ;BN021;
          .repeat                                                       ;BN021;
            lodsb                                                       ;BN021;
            dff_force_NULL:                                             ;BN021;
            stosb                                                       ;BN021;
            or      al,al                                               ;BN021;
            .leave  z                                                   ;BN021;
            dec     cx                                                  ;BN021;
            .if     z                                                   ;BN021;
              xor     al,al                                             ;BN021;
              dec     edi                                               ;BN021;
              jmp     short dff_force_NULL                              ;BN021;
            .endif                                                      ;BN021;
          .until                                                        ;BN021;
                                                                        ;BN013;
          ;------ prepare to return                                     ;BN013;
          mov     ecx,8                 ;volume label only on the 1st pass
          mov     eax,es:[_demFindFirstHack_head]   ;eax=return buffer address
                                                                        ;BN013;
        .endif                                                          ;BN013;
                                                                        ;BN013;
        ret                                                             ;BN013;
EndProc dem_FFHack                                                      ;BN013;

SWAP32_28  segment
;---------------------------------------------------------------------- ;BN013;

;***LP  demNameTrans - Convert Abbreviated Filespec to Fully Qualified Spec
;
;       Convert abbreviated Filespec to Fully Qualified Spec
;
;       ENTRY
;           VSF(DS:SI)
;               Address of unqualified spec
;           VSF(ES:DI)
;               Address of return buffer
;
;       EXIT
;           SUCCESS
;               CF = 0
;           FAILURE
;               CF = 1
;               AX = ERROR_PATH_NOT_FOUND
;
;       HARD ERROR EXIT
;           CF = 1
;           AX = 0FFFFh
;
;       CONTEXT
;           Called from Virtual Mode
;           Executes in Kernel
;
;       STEPS
;           Get registers from frame
;           call w_NameTrans
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;           demMapESDI
;           demMapDS
;           w_NameTrans
;
;       USES
;           EAX,EBX,ECX,EDX,ESI,EDI,EBP,DS,ES
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING
        align   4

Procedure demNameTrans,near
        call    demMapESDI              ; ES:DI = destination buffer
        ASSUME  ES:NOTHING
        mov     esi,[ebx].vsf_esi
        call    demMapDS                ; DS:SI = source buffer
        ASSUME  DS:NOTHING
        CALL16  w_NameTrans
        ret
EndProc   demNameTrans
SWAP32_28  ends

SWAP32_25  segment
;***LP  demChMod - Query/set file attributes
;
;       Query/set file attributes
;
;       ENTRY
;           VSF(DS:DX)
;               Address of filespec
;           GET ATTRIBUTES
;               AL = 0
;           SET ATTRIBUTES
;               AL = 1
;               VSF(CL) = new attributes
;
;       EXIT
;           SUCCESS
;               CF = 0
;               GET ATTRIBUTES
;                   VSF(CL) = new attributes
;           FAILURE
;               CF = 1
;               AX = error code
;
;       HARD ERROR EXIT
;           CF = 1
;           AX = 0FFFFh
;
;       CONTEXT
;           Called from Virtual Mode
;           Executes in Kernel
;
;       STEPS
;           Get registers from frame
;           call w_ChMod
;           Store registers into frame
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;           demMapDSDX
;           w_ChMod
;
;       USES
;           EAX,ECX,EDX,ESI,EDI,ES
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING
        align   4

Procedure demChMod,near

LocalVar  ulFunc,DWORD                          ; only low byte is significant

        EnterProc <eax>
        mov     ecx,[ebx].vsf_ecx
        call    demMapDSDX
        ASSUME  DS:NOTHING
        push    ebx
        mov     al,ulFunc.lobyte
        CALL16  w_ChMod
        FlatContext <ds>,ebx
        pop     ebx
        .if     nc                              ; exit if error
          mov     eax,ulFunc                    ; restore EAX           ;BN003
          .if     <<ulFunc.lobyte> eq 0>
            mov     [ebx].vsf_cx,cx             ; return attribute
          .endif
        .endif
        LeaveProc
        ret
EndProc   demChMod
SWAP32_25  ends

;***LP  demDup - Duplicate a file handle
;
;       Duplicate a file handle (really only re-opens the SF entry)
;
;       ENTRY
;           VSF(BX)
;               Handle to DUP (real handle)
;
;       EXIT
;           SUCCESS
;               CF = 0
;           FAILURE
;               CF = 1
;               AX = error code
;
;       HARD ERROR EXIT
;           CF = 1
;           AX = 0FFFFh
;
;       CONTEXT
;           Called from Virtual Mode
;           Executes in Kernel
;
;       STEPS
;           call SFFromHandle to get SF pointer
;           call DOS_Dup
;
;       NOTES
;           $Dup and $Dup2 end up here.  We only re-open the SFT,
;           leaving the fake handle maintenance to the V86 kernel.
;
;       WARNINGS
;           None
;
;       CALLS
;           DOS_Dup
;
;       USES
;           EAX,EBX,ECX,EDX,ESI,EDI,DS,ES
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING
        align   4

Procedure demDup,near
        EnterProc
        mov     ebx,[ebx].vsf_ebx       ; (BX) = handle
        CALL16  SFFromHandle
        ASSUME  DS:NOTHING,ES:NOTHING
        .if     nc                      ; kill VDM if can't get SF entry
          CALL16  DOS_Dup               ; re-open the SF entry
        .endif
        LeaveProc
        ret
EndProc   demDup

;***LP  demCommit - Commit pending I/O for specified handle
;
;       Commit pending I/O for specified handle
;
;       ENTRY
;           VSF(BX)
;               Handle to commit (real handle)
;
;       EXIT
;           SUCCESS
;               CF = 0
;           FAILURE
;               CF = 1
;               AX = error code
;
;       HARD ERROR EXIT
;           CF = 1
;           AX = 0FFFFh
;
;       CONTEXT
;           Called from Virtual Mode
;           Executes in Kernel
;
;       STEPS
;           Get handle from stack frame
;           call w_3xBufReset
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;           w_3xBufReset
;
;       USES
;           EAX,EBX,ECX,EDX,ESI,EDI,DS,ES
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING
        align   4

Procedure demCommit,near
        mov     ebx,[ebx].vsf_ebx
        CALL16  w_3xBufReset
        ret
EndProc   demCommit

SWAP32_22 segment      ;   wdm  merge 77963 and performance work
;***LP  demMakeFcb - parse file name into fcb
;
;       Parse file name for $parse_file_descriptor
;
;       ENTRY
;           AL
;               parse flags
;           VSF(DS:SI)
;               File name to parse
;           VSF(ES:DI)
;               FCB to file in
;
;       EXIT
;           AL
;               return parse flags
;
;       CONTEXT
;           Called from Virtual Mode
;           Executes in Kernel
;
;       STEPS
;           call MakeFcb
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;           demMapDS
;           demMapESDI
;           MakeFcb
;
;       USES
;           EAX,EBX,ECX,EDX,ESI,EDI,DS,ES
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING
        align   4

Procedure demMakeFcb,near
LocalVar dummycds,<SIZE curdir>
        EnterProc

        push    ebx
        mov     ebx,[_pTCBCur]           ;### PTR B720732
        lea     dx,dummycds
        mov     [ebx].TCBpTmpCDS.Offst,dx
        pop     ebx

        call    demMapESDI
        ASSUME  ES:NOTHING
        mov     esi,[ebx].vsf_esi
        call    demMapDS
        ASSUME  DS:NOTHING
        push    ebx
        CALL16  MakeFcb
        pop     ebx
        FlatContext <ds>,edx
        mov     [ebx].vsf_si,si
        LeaveProc
        ret
EndProc   demMakeFcb
SWAP32_22 ENDS          ;   wdm merge 77963 and performance work

;***LP  demEnumAttrib - enumerate EAs for a specific file
;       int 21 worker for DosEnumAttribute API
;
;       ENTRY
;           AL  - 0     (reserved ??)
;           VSF(DS:SI)
;               ptr to parameter packet
;
;       EXIT
;          CY if error. AX = error code
;
;       CONTEXT
;           Called from Virtual Mode
;           Executes in Kernel
;
;       STEPS
;           convert handle if handle based
;           call w_3xEnumAttrib
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;           demMapDS
;           w_3xEnumAttrib
;
;       USES
;           EAX,EBX,ECX,EDX,ESI,EDI,DS,ES
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING
        align   4

Procedure demEnumAttrib,near
        push    ebx
        mov     esi,[ebx].vsf_esi
        push    [ebx].vsf_ebx           ; real handle
        call    demMapDS                ; DS:SI = parameter packet
        ASSUME  DS:NOTHING
        pop     ebx                     ; bx = REAL HANDLE
        CALL16  w_3xEnumAttrib          ;
        FlatContext <ds>,ebx
        pop     ebx
        ret
EndProc   demEnumAttrib

;***LP  demQMaxEASize - query file system for maximum ea size supported
;
;       ENTRY
;           AL  - 0     (reserved ??)
;           VSF(DS:SI)
;               buffer where the max size is reported on return
;           VSF(ES:DI)
;               path name
;       EXIT
;          CY if error. AX = error code
;
;       CONTEXT
;           Called from Virtual Mode
;           Executes in Kernel
;
;       STEPS
;           set up fsctl arg frame on stack
;           call w_FSCtl
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;           demMapDS
;           demMapESDI
;           w_FSCtl
;
;       USES
;           EAX,EBX,ECX,EDX,ESI,EDI,DS,ES
;
        ASSUME  DS:FLAT,ES:FLAT,SS:TASKAREA,FS:NOTHING,GS:NOTHING
        align   4

Procedure demQMaxEASize,near

LocalVar        easz_ArgFrame, <size FileSysCtlStruc>
LocalVar        easz_ScratchVar,WORD

        EnterProc

        push    ebx
        call    demMapESDI              ; (ES:DI) -> path name
        mov     esi,[ebx].vsf_esi
        call    demMapDS                ; DS:SI = buffer
        ASSUME  DS:NOTHING,ES:NOTHING
        lea     bx,easz_ArgFrame        ; SS:BX -> argframe
        mov     word ptr ss:[bx].hiword,0 ; zero out reserved dword
        mov     word ptr ss:[bx].loword,0
        mov     ss:[bx].FSC_iRouteMethod,FSCTL_PATHROUTE
        mov     ss:[bx].FSC_iFileHandle,-1
        mov     ss:[bx].FSC_szRouteName.Segmt,ES
        mov     ss:[bx].FSC_szRouteName.Offst,DI
        mov     ss:[bx].FSC_iFunction,FSCTL_MAXEASIZE
        lea     ax,easz_ScratchVar              ; SS:AX -> scratch variable
        mov     ss:[bx].FSC_pParmLenOut.Offst,ax; won't be used
        mov     ss:[bx].FSC_pParmLenOut.Segmt,ss
        mov     ss:[bx].FSC_cbParmLength,0
        mov     ss:[bx].FSC_pParmList.Offst,ax  ; won't be used
        mov     ss:[bx].FSC_pParmList.Segmt,ss
        mov     ss:[bx].FSC_pDataLenOut.Offst,ax; won't be used
        mov     ss:[bx].FSC_pDataLenOut.Segmt,ss
        mov     ss:[bx].FSC_cbDataLength,size EASizeBuf
        mov     ss:[bx].FSC_pDataArea.Segmt,DS
        mov     ss:[bx].FSC_pDataArea.Offst,SI
        mov     ax,FSCTL_PATHROUTE      ; route by path name
        mov     cx,-1

;------ SS:BX -> stack frame parms
        CALL16  w_FSCtl                 ;
        FlatContext <ds>,ebx
        pop     ebx

        LeaveProc
        ret
EndProc   demQMaxEASize


;***LP  demMapSegFixup - Map a segment into the specified selector using;BN002;
;                        a fixup if necessary.                          ;BN002;
;                                                                       ;BN002;
;       Take the contents of the EAX register and map a temporary       ;BN002;
;       selector to it. If necessary, fixup the segment and offset      ;BN002;
;       so they avoid the last 16 bytes at the end of the 1 MEG - 16    ;BN002;
;       bytes (FFFF) memory boundary since it is mapped as a UVIRT page.;BN002;
;                                                                       ;BN002;
;       ENTRY                                                           ;BN002;
;           EAX = Segment to map                                        ;BN002;
;           EDI = Offset                                                ;BN002;
;           EDX = Index of selector in aseldemTemp array                ;BN002;
;                                                                       ;BN002;
;       EXIT                                                            ;BN002;
;           SUCCESS                                                     ;BN002;
;               AX  = maps the specified linear address = selector      ;BN002;
;               EDI = offset (normalized if necessary)                  ;BN002;
;           ERROR                                                       ;BN002;
;               InternalError                                           ;BN002;
;                                                                       ;BN002;
;       CONTEXT                                                         ;BN002;
;           Task time                                                   ;BN002;
;                                                                       ;BN002;
;       STEPS                                                           ;BN002;
;           call demMapSegX                                             ;BN002;
;                                                                       ;BN002;
;       CALLS                                                           ;BN002;
;           demMapSegX                                                  ;BN002;
;                                                                       ;BN002;
;       USES                                                            ;BN002;
;           EAX, EDI if fixup neccesary                                 ;BN002;
;                                                                       ;BN002;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING        ;BN002;
        align   4                                                       ;BN002;
                                                                        ;BN002;
Procedure demMapSegFixup,near                                           ;BN002;
        push    ecx                                                     ;BN002;
        .if     <edi ge 10h> and                                        ;BN002;
        .if     <eax eq 0FFFFh>                                         ;BN002;
          sub     edi,10h                                               ;BN002;
          inc     eax                                                   ;BN002;
        .endif                                                          ;BN002;
        call    demMapSegX                                              ;BN002;
        pop     ecx                                                     ;BN002;
        ret                                                             ;BN002;
EndProc   demMapSegFixup                                                ;BN002;


SWAP32_20 segment    ;   wdm merge 77963 and performance work
;***LP  demMapDS - Map ds segment to a selector
;***LP  demMapDSDX - Map ds segment to a selector and return dx
;
;       Take the V86 mode ds segment register and map a temporary
;       selector to it.
;
;       ENTRY
;           EBX = pvsf
;
;       EXIT
;           SUCCESS
;               DS = selector
;               DS:EDX = sel:off if demMapDSDX
;           ERROR
;               InternalError
;
;       CONTEXT
;           Task time
;
;       STEPS
;           call demMapSegX
;
;       CALLS
;           demMapSegX
;
;       USES
;           DS, EDX if demMapDSDX
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING
        align   4

Procedure demMapDSDX,near
        movzx   edx,[ebx].vsf_dx

Entry   demMapDS
        push    eax
        push    ecx
        push    edx
        movzx   eax,[ebx].vsf_ds        ; (EAX) = ds segment
        mov     edx,ISELDEMDS
        call    demMapSegX
        mov     ds,eax
        pop     edx
        pop     ecx
        pop     eax
        ret
EndProc   demMapDSDX
SWAP32_20 ENDS        ;  wdm  merge 77963 and performance work
SWAP32_20 segment    ;  wdm  merge 77963 and performance work

;***LP  demMapES - Map es segment to a selector                         ;BC002;
;***LP  demMapESDI - Map es segment to a selector and return di         ;BC002;
;
;       Take the V86 mode es segment register and map a temporary
;       selector to it.
;
;       ENTRY
;           EBX = pvsf
;
;       EXIT
;           SUCCESS
;               ES = selector
;               ES:EDI = sel:off if DemMapESDI
;           ERROR
;               InternalError
;
;       CONTEXT
;           Task time
;
;       STEPS
;           call demMapSegX
;
;       CALLS
;           demMapSegX
;
;       USES
;           ES, FS, GS, EDI if DemMapESDI
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING
        align   4

Procedure demMapESDI,near
        movzx   edi,[ebx].vsf_di

Entry   demMapES
        push    eax
        push    ecx
        push    edx
        movzx   eax,[ebx].vsf_es        ; (EAX) = ds segment
        mov     edx,ISELDEMES
        call    demMapSegX
        mov     es,eax
        pop     edx
        pop     ecx
        pop     eax
        ret
EndProc   demMapESDI
SWAP32_20 ENDS        ;  wdm  merge 77963 and performance work

SWAP32_22 segment     ;  wdm  merge 77963 and performance work
;***LP  demMapSeg - Map selector onto the specified segment
;
;       Take a V86 mode segment and map temporary a selector to it.
;
;       ENTRY
;           AX
;               Segment to map
;
;       EXIT
;           SUCCESS
;               AX maps the specified linear address
;           ERROR
;               InternalError
;
;
;       CONTEXT
;           Task time
;
;       STEPS
;           call demMapSegX
;
;       CALLS
;           demMapSegX
;
;       USES
;           EAX,FS,GS
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING
        align   4

Procedure demMapSeg,<near,far32>
        push    ecx
        push    edx
        xor     edx,edx
        .errnz  ISELDEMTEMP
        movzx   eax,ax                  ; zero the high word            ;BN002;
        call    demMapSegX
        pop     edx
        pop     ecx
        ret
EndProc   demMapSeg
SWAP32_22 ENDS        ; wdm  merge 77963 and performance work

;***LP  demMapSegLenCX - Map selector onto the specified segment with length CX
;
;       Take a V86 mode segment and map temporary a selector to it to with the
;       length specified in CX.
;
;       ENTRY
;           AX
;               Segment to map
;           CX
;               Length of selector
;
;       EXIT
;           SUCCESS
;               AX maps the specified linear address
;           ERROR
;               InternalError
;
;
;       CONTEXT
;           Task time
;
;       STEPS
;           call demMapSegX
;
;       CALLS
;           demMapSegX
;
;       USES
;           EAX,FS,GS
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING
        align   4

Procedure demMapSegLenCX,<near,far32>
        push    ecx
        push    edx
        xor     edx,edx
        .errnz  ISELDEMTEMP
        movzx   eax,ax                  ; zero the high word
        shl     eax,4                   ; (EAX) = the linear address
        call    demMapVirt
        pop     edx
        pop     ecx
        ret
EndProc   demMapSegLenCX

SWAP32_20 segment     ;  wdm  merge 77963 and performance work
;***LP  demMapSegX - Map a selector onto the specified segment
;
;       Take a V86 mode segment and map a temporary selector to it
;
;       ENTRY
;           EAX                                                         ;BC002;
;               Segment to map
;           EDX
;               Index of selector in aseldemTemp array
;
;       EXIT
;           SUCCESS
;               AX maps the specified linear address
;           ERROR
;               InternalError
;
;
;       CONTEXT
;           Task time
;
;       STEPS
;           Convert segment to linear address
;           call demMapVirt
;
;       NOTES
;           None
;
;       WARNINGS
;           The selector is only valid in the current context.  The
;           page might not be present, so a reference to the selector
;           might cause a page fault and context switch.
;
;           We map 65536 bytes.
;
;       CALLS
;           demMapVirt
;
;       USES
;           EAX,ECX,EDX,FS,GS
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING
        align   4

Procedure demMapSegX,near
        shl     eax,4                   ; (EAX) = the linear address
        mov     ecx,[vdmid_RMSIZE]
        shl     ecx,0ah                 ; (ECX) = RMSIZE in bytes
        sub     ecx,eax
        .if     be or                   ; JB-->JBE                      ;BC018;
        .if     <ecx ae 10000h>         ; is mapping needed for < 64k   ;BC002;
          mov     ecx,10000h            ; (ECX) = size (64K)
        .endif                                                          ;BC002;
        align   4                                                       ;BN002;
if2
        .errnz  $-demMapVirt
endif
EndProc   demMapSegX
SWAP32_20 ends

SWAP32_20 segment
;***LP  demMapVirt - Map a selector onto the specified linear address
;
;       Take a linear address and map a temporary selector to it
;
;       ENTRY
;           EAX
;               Linear address to map
;           ECX
;               Size of range to map
;           EDX
;               Index of selector in aseldemTemp array
;
;       EXIT
;           SUCCESS
;               AX contains selector that maps the specified linear address
;           ERROR
;               InternalError
;
;       CONTEXT
;           Task time
;
;       STEPS
;           Get selector
;           Call SELSetDescInfo
;
;       NOTES
;           None
;
;       WARNINGS
;           The selector is only valid in the current context.  The
;           page might not be present, so a reference to the selector
;           might cause a page fault and context switch.
;
;           We map 65536 bytes.
;
;       CALLS
;           SELSetDescInfo
;
;       USES
;           EAX,ECX,EDX,FS,GS
;
        ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING,FS:NOTHING,GS:NOTHING

Procedure demMapVirt,near
        SaveReg <ebx,ds,es>             ; save for later
        FlatContext <ds,es>,ebx         ; ES needed flat for C-routine, below
        movzx   ebx,aseldemTemp[edx*2]  ; (EBX) = address of selector

;       (EAX) = laddr, (EBX) = sel, (ECX) = size

        CCALL32 SELSetDescInfo, <SELSD_ALL, D_DATA0, ebx, ecx, eax, 0, 0, 0>
        mov     eax,ebx                 ; (EAX) = selector
        RestoreReg <es,ds,ebx>          ; restore registers
        ret
EndProc   demMapVirt
SWAP32_20 ends

SWAP32_25 segment
;***LP  demGetLin - Get Linear address of es:di
;
;       get Linear address of es:di
;
;       ENTRY
;           es:di on vsf
;
;       EXIT
;           SUCCESS
;               EAX has the linear address
;
;       CONTEXT
;           Task time
;
;       STEPS
;           Convert a seg:offset to linear
;
;       NOTES
;           None
;
;       USES
;           EAX,EDI
;
        ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING,FS:NOTHING,GS:NOTHING

Procedure demGetLin,near
        movzx   eax,[ebx].vsf_es
        movzx   edi,[ebx].vsf_di
        rol     eax,4
        add     eax,edi
        ret
EndProc   demGetLin

SWAP32_25 ends

SWAP32_22 segment   ;   wdm  merge 77963 and performance work
;***LP  demSetEAField - Set the TCBNewFlags field if the DOS APP
;                       is EA aware.
;
;       ENTRY
;           VSF(AX)
;               0 - if not EA Aware
;               1 - if EA Aware
;
;       EXIT
;           None
;
;       CONTEXT
;           Called from Virtual Mode
;           Executes in Kernel
;
;
;       USES
;           ESI,AX
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING
        align   4

Procedure demSetEAField,near

        mov     esi,[_pTCBCur]          ; (ESI) = pointer to TCB
        mov     ax,[ebx].vsf_ax         ; (AX) = EA aware or not
        and     [esi].TCBNewFlags, not TCBKNOWEAS
                                        ; By default app is not EA aware
        or      ax,ax
        .if     nz
          or      [esi].TCBNewFlags,TCBKNOWEAS
        .endif

        ret
EndProc   demSetEAField

SWAP32_22 ENDS      ;   wdm  merge 77963 and performance work
EndCode

        END
