        page    ,132
        title   DemPath2.asm

;***EM  dempath2.asm
;
;       SCCSID = @(#)dempath2.asm       6.14 92/03/29
;
;       SUMMARY
;           DOS Emulation File System Path Function Support
;
;       NOTES
;
;       REVISIONS
;
;Local  DCR/
;Tag    PTR     Who     When
;               danno   08-Mar-1989
;                   Created for MVDM
;********************************************************************** ;BN001;
; 26Oct91 - G.L.Fulk                                                    ;BN001;
; Add a new Generic call worker (#4) to return the JFT size in the PTDA.;BN001;
;********************************************************************** ;BN001;
; 31Oct91 - G.L.Fulk                                                    ;BN002;
; Add the user environment to the Delete and FCBDelete FS worker calls. ;BN002;
;********************************************************************** ;BN002;
; 06Nov91 - G.L.Fulk                                                    ;BN003;
; Add the new API call for DosForceDelete.                              ;BN003;
;********************************************************************** ;BN003;
; 06Nov91 - P.C.Rodriguez                                               ;BN004;
; Replace call to w_Unlink with w_StoreFile3x (for Undelete)            ;BN004;
;********************************************************************** ;BN004;
; 9Nov91 - PaulDev - fix build break, ptr b729590 - bring back          ;BN005;
; demSetTitle. Just copied entire deleted routine back in from the      ;BN005;
; previous version of the file.                                         ;BN005;
;********************************************************************** ;BN005;
; 05Feb92 - G.L.Fulk                                                    ;BN006;
; Add DOS32 Semaphore interfaces.                                       ;BN006;
;********************************************************************** ;BN006;
; 05Feb92 - G.L.Fulk                                                    ;BN007;
; Add Function 64h, special request 5 (return SFT2 flags).              ;BN007;
;********************************************************************** ;BN007;
; 15Feb92 - G.L.Fulk                                                    ;BN008;
; The Forced delete worker in File System sets the CY/NC to indicate an ;BN008;
; error, and leaves junk in the AX register.  Therefore, we cannot      ;BN008;
; depend on AX having a 0 for successful operation.                     ;BN008;
;********************************************************************** ;BN008;
; 20Feb92 - G.L.Fulk                                                    ;BN009;
; Use the "FlatContext" macro instead of hard coding FLAT selector 168. ;BN009;
;********************************************************************** ;BN009;
; 22Feb92 - G.L.Fulk                                                    ;BN010;
; Add DosGetCP API.                                                     ;BN010;
;********************************************************************** ;BN010;
; 3/29/92 - Mark Rogalski                                               ;BN011;
; CP20 AA05005  For FCB_Delete, if ES is zero, keep it that way.        ;BN011;
;********************************************************************** ;BN011;
; 07Aug92 - G.L.Fulk                                                    ;BN012;
; Add a new back-door int 21h "generic" call to unload the DOSKRNL.SYM  ;BN012;
; symbols and load in it's place another symbol file.                   ;BN012;
;********************************************************************** ;BN012;
; 28Aug92 - G.L.Fulk                                                    ;26159;
; Add DOS32STARTSESSION interface.                                      ;26159;
;********************************************************************** ;26159;
; 18Feb93 - G.L.Fulk                                                    ;58348;
; Add a new parameter to the DosCreateVDM API to pass current drive and ;58348;
; sub-directory information.                                            ;58348;
;********************************************************************** ;58348;
; 22Feb93 - G.L.Fulk                                                    ;60981;
; Quicken for Windows has an install quirk that's dependant on a DOS    ;60981;
; file system bug.... Open a file, delete the file, close the file.     ;60981;
; This hack will permit this to work now.                               ;60981;
;********************************************************************** ;60981;
; 25Feb93 - L.M.Primm                                                   ;62949;
; Need to zero extend edi after return from f_SFFromHandle              ;62949;
;********************************************************************** ;62949;
; 03Mar93 - L.M.Primm                                                   ;62331;
; PALASM (a DOS app) had similar problem to Quicken for Windows except  ;62331;
; that PALASM did not pass in a fully-qualified pathname.  Altered      ;62331;
; demQuickenHack to handle non-fully-qualified filenames and keep       ;62331;
; looking through open files for all instance of that filename.         ;62331;
;********************************************************************** ;62331;
; 13Apr93 - Fulkgl                                                      ;65622;
; The timing and sync of DemStartSession needs to be changed to fix a   ;65622;
; problem with video.                                                   ;65622;
;********************************************************************** ;65622;
; 13Jul93 - Fulkgl                                                      ;70592;
; Change drive and sub-directory on DemStartSession.                    ;70592;
; Extra: Added new i21.64 generic function 9 to return drive lock state.;70592;
;********************************************************************** ;70592;
; 13Sep93 - ChangeTeam                                                  ;73751;
; Add check for AX=0(Windows running) in demDelete.                     ;73751;
;    This is needed because Windows, for some reason, converts the addr.;73751;
;    of the environment var from segm to selctr before this call.       ;73751;
;********************************************************************** ;73751;
; 08Oct93 - Uday Parekh                                                 ;74035;
; This mainly applies to subst command.                                 ;74035;
; Logical path and program name were changed to physical path and       ;74035;
; program name when DOS VDM tries to create another dos vdm.            ;74035;
; _dosStartSession_CDS and _demStartSession_data.demSS_DataPgmName      ;74035;
; gets modified from Logical to Physical if CDS is substituted.         ;74035;
; demSubstPhys function and XCHGP32 macro were created.                 ;74035;
;**********************************************************************
; 19Sep94 - bjn
; Change segment names for page tuning.
;**********************************************************************
; 07Sep94 - ChangeTeam                                                  ;92113;
; Modified fix added for defect 80482. To determine whether a selector  ;92113;
; or a segment was given, the DPMI Host Data Block linked list is       ;92113;
; queried.                                                              ;92113;
;********************************************************************;105001;
; 15 Nov 94 - Change Team   Defect 92113 added to Warp verision of demdelete routine.;105001;
; Defect 80482 was never added to warp and since 92113 removes it, it will not be added here.;105001;
;********************************************************************** ;105001;
;
;   Throughout the routines in this file, when loading registers
;   from the client stack frame, we will perform a 32-bit load.
;   Generally, the upper-16 bits of the register are ignored and
;   only the lower 16-bits are needed.  This is done only to avoid
;   an override.
;
;   When storing registers into the stack frame, however, we always
;   perform 16-bit stores, since the upper 16-bits of the 32-bit
;   registers are reserved *exclusively* for DOS applications.
;
;   -- danno 08-Mar-1989

INCL_NONE       equ     1                       ;dont include everything;26159;
INCL_VDHALL     equ     1                       ; include VDH services  ;26159;
INCL_TYPES      equ     1                       ; include basic types   ;26159;
INCL_DEF        equ     1                       ; include typedef macros

.xlist
.xcref
include fnomvdm.inc                                                     ;26159;
include dosseg.inc
include basemaca.inc
include osmaca.inc
include osconst.inc                                                     ;26159;
include dossymc.inc
include infoseg.inc                                                     ;26159;
include sigdef.inc                                                      ;26159;
include except.inc                                                      ;26159;
include pgexport.inc                                                    ;26159;
include vmexport.inc                                                    ;26159;
include selxport.inc                                                    ;26159;
include tkexport.inc                                                    ;26159;
include dirent.inc                                                      ;26159;
include curdir.inc
include find.inc                                                        ;26159;
include screen.inc                                                      ;26159;
include sft.inc                                                         ;BN007;
include mft.inc                                                         ;60981;
include sem.inc                                                         ;26159;
include seldesc.inc                                                     ;26159;
include protmode.inc                                                    ;26159;
include chardd.inc                                                      ;26159;
include dos3dev.inc                                                     ;26159;
include filesys.inc                                                     ;26159;
include inbuf.inc                                                       ;26159;
include dbcs.inc                                                        ;26159;
include argframe.inc
include opncreat.inc                                                    ;26159;
include dem.inc                                                         ;26159;
include error.inc
include extattr.inc                                                     ;26159;
include kmode.inc
include mult.inc                                                        ;26159;
include pdb.inc                                                         ;26159;
include mi.inc
include vpb.inc                                                         ;26159;
include fsc.inc                                                         ;26159;
include mvdm.inc                                                        ;26159;
include sysentry.inc                                                    ;26159;
include devsym.inc                                                      ;26159;
include struc30.inc                                                     ;BN001;
include vdmvdh.inc                                                      ;26159;
include mmpha.inc                                                       ;BN006;
include ordinals.inc
include bseord.inc                                                      ;26159;
include sysserv.inc                                                     ;26159;
include demsmg.inc                                                      ;26159;
include dpb.inc                                                         ;70592;
include vpmxport.inc                                               ;92113;105001;
.cref
.list


        CpuMode 386

        ReferTask       JFN_Length,WORD                                 ;BN001;
        ReferTask       Cons_Loc,BYTE                                   ;56655;
        ReferTask       LCurDrv,BYTE                                    ;56655;
        ReferFlat       CallGate_Debug_SymWinOS2,WORD
        ReferTask       CurrentPDB,WORD                                 ;60981;
        extrn   dem_handle_Close: near                                  ;60981;
        EXTRN16 w_Current_Dir
        EXTRN16 Find_VPB                                                ;70592;
        EXTRN16 w_ChDir
        EXTRN16 w_RmDir
        EXTRN16 w_MkDir
        EXTRN16 w_FCB_Rename
        EXTRN16 w_FCB_Delete
        EXTRN16 w_StoreFile3x                                           ;BN004;
        EXTRN16 w_Rename
        EXTRN16 GSetMediaID
        EXTRN16 w_qFSAttach
        EXTRN16 w_EditName
        EXTRN16 w_Unlink                                                ;BN003;
        EXTRN16 w_Shutdown                                              ;125881
        EXTRN16 SFFromHandle                                            ;BN007;
        EXTRN16 w_GetCp                                                 ;BN009;
        EXTRN16 SysServQueueEvent                                       ;26159;
        EXTRN16 TransPath                                               ;62331;
        EXTRN16 ListCDSText                                             ;74035;

DefData IMPORT, SWAPINST, C                                             ;92113;105001;
PDHD    pdhdHostData                            ; em86vpm.c             ;92113;105001;
PDHD    pdhdHostLast                            ; em86vpm.c             ;92113;105001;
EndData                                                                 ;92113 ;105001;

DefCode IMPORT, SWAP, C
DefFn   vdmmGetTitle
DefFn   vdmmSetTitle
EndCode

DefCode IMPORT, SWAP
DefFn   demMapSeg
DefFn   demMapVirt                                                      ;70592;
DefFn   demMapDSDX
DefFn   demMapDS
DefFn   demMapES                                                        ;BN002;
DefFn   demMapESDI
DefFn   demGetLin
EndCode

        EXTRN   _VR32CreateEventSem:near                                ;26159;
        EXTRN   _VR32OpenEventSem:near                                  ;26159;
        EXTRN   _VR32CloseEventSem:near                                 ;26159;
        EXTRN   _VR32ResetEventSem:near                                 ;26159;
        EXTRN   _VR32PostEventSem:near                                  ;26159;
        EXTRN   _VR32WaitEventSem:near                                  ;26159;
        EXTRN   _VR32QueryEventSem:near                                 ;65622;
                                                                        ;26159;
        EXTRN   _VR32CreateMutexSem:near                                ;26159;
        EXTRN   _VR32OpenMutexSem:near                                  ;26159;
        EXTRN   _VR32CloseMutexSem:near                                 ;26159;
        EXTRN   _VR32RequestMutexSem:near                               ;26159;
        EXTRN   _VR32ReleaseMutexSem:near                               ;26159;
        EXTRN   _VR32QueryMutexSem:near                                 ;65622;
                                                                        ;26159;
        EXTRN   _VR32CreateMuxWaitSem:near                              ;65622;
        EXTRN   _VR32OpenMuxWaitSem:near                                ;26159;
        EXTRN   _VR32CloseMuxWaitSem:near                               ;26159;
        EXTRN   _VR32WaitMuxWaitSem:near                                ;26159;
        EXTRN   _VR32AddMuxWaitSem:near                                 ;65622;
        EXTRN   _VR32DeleteMuxWaitSem:near                              ;65622;
        EXTRN   _VR32QueryMuxWaitSem:near                               ;65622;
                                                                        ;26159;
        EXTRN   _demSS_curr: DWORD              ;type ULONG             ;65622;
        EXTRN   _demSS_next: DWORD              ;type ULONG             ;65622;
        EXTRN   _demSS_us: DWORD                ;type ULONG             ;65622;
        EXTRN   _demVDMStartCount: DWORD        ;type ULONG             ;65622;
        EXTRN   _demVDMStartDoneHndl:DWORD      ;type HEV               ;26159;
        EXTRN   _demStartSession_data:DWORD                             ;26159;
        EXTRN   _demStartSession_CDS:BYTE                               ;58348;
        EXTRN   _demStartSession_CDS_lowmem:BYTE                        ;70592;
CONSTANTS       SEGMENT                                                 ;26159;
        EXTRN   SMDosSessionQ:BYTE                                      ;26159;
CONSTANTS       ENDS                                                    ;26159;
                                                                        ;26159;
        FARCODE HIGH32
DefCode PRIVATE, SWAP, PASCAL

SWAP32_22 segment
;***LP  demQueryCurrentDir - Return current directory of specified drive
;
;       ENTRY
;           EBX = address of VSF
;           VSF(DS:SI) = Address of 64-byte return buffer
;           VSF.DL = Drive to query (0=def, 1=A, ...)
;
;       EXIT
;           SUCCESS
;               CY = 0
;               AX = INT21_47_SUCCESS                                   ;D74507;
;               Buffer written
;           FAIL
;               CY = 1
;               AX = error code
;           HARD ERROR
;               CY = 1
;               AX = 0FFFFh
;
;       CONTEXT
;           Called from Virtual Mode
;           Executes in Kernel
;
;       STEPS
;           Map segment to selector
;           cal w_Current_Dir
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;           demMapSeg
;           w_Current_Dir
;
;       USES
;           EAX,EBX,ECX,EDX,ESI,EDI,DS,ES
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,GS:NOTHING,FS:NOTHING
        align   4

Procedure demQueryCurrentDir,near
        mov     eax,dword ptr [ebx].vsf_ds  ; Get buffer segment
        call    demMapSeg                   ; Map a selector into AX
        mov     dl,[ebx].vsf_dl             ; Get drive
        mov     si,[ebx].vsf_si
        mov     cx,RMDIRSTRLEN              ; Set maximum length (64--*not*67)
        mov     ebx,eax                     ; w_Current_Dir wants selector in BX
        CALL16  w_Current_Dir               ; Do the rest
        ret
EndProc   demQueryCurrentDir
SWAP32_22 ends

SWAP32_22 segment
;***LP  demSetCurrentDir - Set current directory of specified drive
;
;       ENTRY
;           EBX = address of VSF
;           VSF(DS:DX) = Address of ASCIIZ drive:path
;
;       EXIT
;           SUCCESS
;               CY = 0
;               Current directory changed for specified drive
;           FAIL
;               CY = 1
;               AX = error code
;           HARD ERROR
;               CY = 1
;               AX = 0FFFFh
;
;       CONTEXT
;           Called from Virtual Mode
;           Executes in Kernel
;
;       STEPS
;           Map segment to selector
;           call w_ChDir
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;           demMapDSDX
;           w_ChDir
;
;       USES
;           EAX,EBX,ECX,EDX,ESI,EDI,DS,ES
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,GS:NOTHING,FS:NOTHING
        align   4

Procedure demSetCurrentDir,near
        call    demMapDSDX                  ; DS:DX --> path
        CALL16  w_ChDir                     ; Do the rest
        ret
EndProc   demSetCurrentDir
SWAP32_22 ends

;***LP  demDeleteDir - Delete a Subdirectory
;
;       ENTRY
;           EBX = address of VSF
;           VSF(DS:DX) = points to directory to delete
;
;       EXIT
;           SUCCESS
;               CY = 0
;               Buffer written
;           FAIL
;               CY = 1
;               AX = system status code
;           HARD ERROR
;               CY = 1
;               AX = 0FFFFh
;
;       CONTEXT
;           Called from Virtual Mode
;           Executes in Kernel
;
;       STEPS
;           Map segment to selector
;           call w_RmDir
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;           demMapDSDX
;           w_RmDir
;
;       USES
;           EAX,EBX,ECX,EDX,ESI,EDI,DS,ES
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,GS:NOTHING,FS:NOTHING
        align   4

Procedure demDeleteDir,near
        call    demMapDSDX                  ; DS:DX --> path
        CALL16  w_RmDir                     ; Delete it
        ret
EndProc   demDeleteDir

;***LP  demCreateDir - Create a Subdirectory
;
;       ENTRY
;           EBX = address of VSF
;           VSF(DS:DX) = points to directory name to Create
;           VSF(BX:SI) = address of EA list (NULL->no EA's)
;
;       EXIT
;           SUCCESS
;               CY = 0
;               Buffer written
;           FAIL
;               CY = 1
;               AX = error code
;           HARD ERROR
;               CY = 1
;               AX = 0FFFFh
;
;       CONTEXT
;           Called from Virtual Mode
;           Executes in Kernel
;
;       STEPS
;           Map EA segment to selector
;           Map name string segment to selector
;           call w_MkDir
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;           demMapDSDX
;           demMapSeg
;           w_MkDir
;
;       USES
;           EAX,EBX,ECX,EDX,ESI,EDI,DS,ES
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,GS:NOTHING,FS:NOTHING
        align   4

Procedure demCreateDir,near
        mov     dx,[ebx].vsf_bx                 ; Get EA buffer segment
        mov     si,[ebx].vsf_si                 ; Get EA buffer offset
        mov     ax,si
        or      ax,dx
        .if     nz                              ; Skip if no EA's       ;BC002;
          mov     ax,dx
          call    demMapSeg                     ; Map EA selector into AX
        .endif
        call    demMapDSDX                      ; DS:DX = path
        assume  ds:nothing
        mov     bx,ax                           ; BX:SI = EA
        push    ebp
        CALL16  w_MkDir                         ; Create it
        pop     ebp
        ret
EndProc   demCreateDir

;***LP  demDeleteFCB - Delete files specified by an FCB
;
;       ENTRY
;           VSF(DS:DX) = points to the FCB
;
;       EXIT
;           SUCCESS
;               CF = 0
;               Files deleted
;           FAIL
;               CF = 1
;               AX = error code
;
;           HARD ERROR
;               CY = 1
;               AX = 0FFFFh
;
;       CONTEXT
;           Called from Virtual Mode
;           Executes in Kernel
;
;       STEPS
;           map segment
;           call w_FCB_Delete
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;           demMapDSDX
;           w_FCB_Delete
;
;       USES
;           EAX,EBX,ECX,EDX,ESI,EDI,DS,ES
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,GS:NOTHING,FS:NOTHING
        align   4

Procedure demDeleteFCB,near
        cmp     [ebx].vsf_es,0
        .if     z                                                       ;BN011;
          push    0                                                     ;BN011;
          pop     es                                                    ;BN011;
        .else                                                           ;BN011;
          call    demMapES                                              ;BN002;
        .endif                                                          ;BN011;
        call    demMapDSDX
        assume  ds:nothing,es:nothing                                   ;BC002;
        CALL16  w_FCB_Delete
        ret
EndProc   demDeleteFCB

;***LP  demRenameFCB - Rename files specified by an FCB
;
;       ENTRY
;           VSF(DS:DX) = points to the FCB
;
;       EXIT
;           SUCCESS
;               CY = 0
;               Files Renamed
;           FAIL
;               CY = 1
;               AX = error code
;               (Some files may have been renamed if one was read-only)
;
;           HARD ERROR
;               CY = 1
;               AX = 0FFFFh
;
;       CONTEXT
;           Called from Virtual Mode
;           Executes in Kernel
;
;       STEPS
;           map segment
;           call w_FCB_Rename
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;           demMapDSDX
;           w_FCB_Rename
;
;       USES
;           EAX,EBX,ECX,EDX,ESI,EDI,DS,ES
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,GS:NOTHING,FS:NOTHING
        align   4

Procedure demRenameFCB,near
        call    demMapDSDX
        assume  ds:nothing
        CALL16  w_FCB_Rename
        ret
EndProc   demRenameFCB

SWAP32_28 segment
;***LP  demDelete - Delete file specified by a ASCIIZ filespec
;
;       ENTRY
;           VSF(DS:DX) = points to the ASCIIZ filespec
;
;       EXIT
;           SUCCESS
;               CY = 0
;               File deleted
;           FAIL
;               CY = 1
;               AX = error code
;
;           HARD ERROR
;               CY = 1
;               AX = 0FFFFh
;
;       CONTEXT
;           Called from Virtual Mode
;           Executes in Kernel
;
;       STEPS
;           map segment
;           call w_StoreFile3x                                          ;BN004;
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;           demMapDSDX
;           w_StoreFile3x                                               ;BN004;
;
;       USES
;           EAX,EBX,ECX,EDX,ESI,EDI,DS,ES
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,GS:NOTHING,FS:NOTHING
        align   4

Procedure demDelete,near
LocalVar  quicken_pvsf,DWORD                                            ;60981;
LocalVar  lmp_beginpath,DWORD                                           ;62331;
LocalVar  lmp_pathbuf,PMPATHLEN                                         ;62331;
        EnterProc <ebx> ;save EBX into quicken_pvsf                     ;60981;
        push    es                                                      ;62331;
        push    ds                                                      ;62331;

;-----------------------------------------------------------------------;92113;105001;
;                     BEGIN CHANGES FOR DEFECT 92113;105001;
;   A DPMI Host Data Block structure gets added to the linked list of HDBs
;   for every dpmi start call in a VDM.  We will use this to determine
;   if the current exe (thru the current pdb) is running in protect mode &=>
;   contains a selector (as opposed to segm) addr for environ var in PDB.
;        IF  ThereAreNoHDBs
;           No protect mode apps running -> ClientEnvAddr must be a segmnt
;        ELSE
;           IF the current HDBselEnviron = ClientEnvAddr
;              ClientEnvAddr is a selctr
;           ELSE
;              Loop thru all HDBs looking for HDBselEnviron match
;              IF no match found
;                 ClientEnvAddr is a segmnt
;              ELSE
;                 ClientEnvAddr is a selctr
;              ENDIF
;           ENDIF
;        ENDIF
;
; '
;-----------------------------------------------------------------------;92113;105001;

        push    ecx
        push    ax
        mov     ax,[ebx].vsf_es                ;CurrentPDB[PDB_environ]
        mov     ecx,pdhdHostData               ;"current" DPMI Host Data Block

        .if <ecx eq 0000h>                     ;there are no DPMI HDBs
           call  demMapES                      ;map PDB_environ segm to selctr
        .else
           .if <[ecx.dhd_selEnviron] eq ax>
              mov  es,ax                       ;PDB_environ is already a selctr
           .else
              mov  ecx,pdhdHostLast

              ;Loop thru DPMI HDBs checking for selEnviron match
              .while <ecx ne 0000h>
                  .if <[ecx.dhd_selEnviron] eq ax>
                     jmp  short demDelExitWhile
                  .endif
                  mov  ecx,[ecx.dhd_pdhdParent] ;get the next DPMI HDB
              .endwhile
demDelExitWhile:
              .if <ecx eq 0000h>              ;no selEnviron match found =>
                 call  demMapES               ;  map PDB_environ segm to selctr
              .else                           ;selEnviron match was found =>
                  mov  es,ax                  ;  PDB_environ is already a selctr
              .endif
           .endif
        .endif

        pop    ax
        pop    ecx
;-----------------------------------------------------------------------;92113;105001;
;                     END CHANGES FOR DEFECT 92113;105001;
;-----------------------------------------------------------------------;92113;105001;

              call    demMapDSDX
        assume  ds:nothing,es:nothing
        CALL16  w_StoreFile3x
        .if     c and near                                              ;60981;
        .if     <AX eq 20h> near                                        ;60981;
public DemQuickenHack                                                   ;60981;
DemQuickenHack:                                                         ;60981;
          movzx   edx,dx                                                ;62331;
          mov     esi,edx                                               ;62331;
          lea     edi,[lmp_pathbuf]                                     ;62331;
          push    ss                                                    ;62331;
          pop     es                                                    ;62331;
          CALL16  TransPath                                             ;62331;
          lea     edi,[lmp_pathbuf]                                     ;62331;
          mov     edx,edi       ; DS:DX now has fully-qualified path    ;62331;
          FlatContext <es>,eax                                          ;60981;
          assume  es:FLAT                                               ;60981;
          movzx   eax,ss:[CurrentPDB]                                   ;60981;
          shl     eax,4                 ;eax=flat addr of current PDB   ;60981;
          movzx   ecx,word ptr es:[eax]+32h     ;=length of DOS JFT     ;60981;
          movzx   edi,word ptr es:[eax]+34h     ;\pointer to DOS JFT    ;60981;
          movzx   esi,word ptr es:[eax]+36h     ;/                      ;60981;
          shl     esi,4                                                 ;60981;
          add     esi,edi               ;esi=flat addr of DOS JFT       ;60981;
          movzx   edx,dx                                                ;60981;
          mov     lmp_beginpath,edx                                     ;62331;
          .repeat                                                       ;60981;
            mov     al,es:[esi]                                         ;60981;
            mov     edx,lmp_beginpath                                   ;62331;
            .if     <AL b 0D0h>                                         ;60981;
              movzx   ebx,al                                            ;60981;
              push    es                                                ;60981;
              CALL16  SFFromHandle      ; get the SF entry              ;60981;
              movzx   edi, di                                           ;62949;
              jc      short quicken_failed                              ;62949;
              assume  es:nothing                                        ;60981;
              ;es:edi=OS/2 SFT entry                                    ;60981;
              mov     edi,es:[edi].sf_MFT                               ;60981;
              add     edi,mft_name                                      ;60981;
              pop     es                                                ;60981;
              assume  es:FLAT                                           ;60981;
              .repeat                                                   ;60981;
                mov     al,ds:[edx]                                     ;60981;
                cmp     al,es:[edi]                                     ;60981;
                jne     short quicken_nomatch                           ;60981;
                inc     edi                                             ;60981;
                inc     edx                                             ;60981;
              .until  <AL eq 0>                                         ;60981;
              push    es                                                ;60981;
              pushad                                                    ;62331;
              call    dem_handle_Close                                  ;60981;
              popad                                                     ;62331;
              pop     es                                          ;62331;60981;
              jc      short quicken_failed                              ;60981;
quicken_nomatch:                                                        ;60981;
            .endif                                                      ;60981;
            inc     esi                                                 ;60981;
          .loop                                                         ;60981;
          assume  ds:FLAT,es:nothing                                    ;62331;
          pop     ds                                                    ;62331;
          pop     es                                                    ;62331;
          mov     ebx,quicken_pvsf                                ;62331;60981;
          call    demMapES                                        ;62331;60981;
          call    demMapDSDX                                      ;62331;60981;
          assume  ds:nothing                                      ;62331;60981;
          CALL16  w_StoreFile3x                                   ;62331;60981;
          jmp     short quicken_done                              ;62331;60981;
quicken_failed:                                                         ;60981;
          pop     ds                                                    ;62331;
          pop     es                                                    ;62331;
          stc                                                           ;60981;
          mov     eax,20h                                               ;60981;
quicken_done:                                                           ;60981;
        .endif                                                          ;60981;
        LeaveProc                                                       ;60981;
        ret
EndProc   demDelete
SWAP32_28 ends

;***LP  demRename - Rename path specified by ASCIIZ strings
;
;       ENTRY
;           VSF(DS:DX) = points to the source ASCIIZ string
;           VSF(ES:DI) = points to the dest ASCIIZ string
;
;       EXIT
;           SUCCESS
;               CY = 0
;               Path Renamed
;           FAIL
;               CY = 1
;               AX = error code
;
;           HARD ERROR
;               CY = 1
;               AX = 0FFFFh
;
;       CONTEXT
;           Called from Virtual Mode
;           Executes in Kernel
;
;       STEPS
;           map segments
;           call w_Rename
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;           demMapDSDX
;           demMapESDI
;           w_Rename
;
;       USES
;           EAX,EBX,ECX,EDX,ESI,EDI,DS,ES
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,GS:NOTHING,FS:NOTHING
        align   4

Procedure demRename,near
        call    demMapESDI
        assume  ds:nothing
        call    demMapDSDX
        assume  ds:nothing
        CALL16  w_Rename
        ret
EndProc   demRename

SWAP32_28 segment
;***LP  demGSetMediaID - Get/Set Media ID
;
;       This routine allows the caller to query or modify the
;       media ID information.
;
;       ENTRY
;           VSF(DS:DX) = points to the buffer
;           VSF(BL) = drive number
;           VSF(BH) = infolevel or 0
;           VSF(CX) = buffer size (iff BH!=0)
;           GET MEDIA ID
;               VSF(AL) = 0
;           SET MEDIA ID
;               VSF(AL) = 1
;
;       EXIT
;           SUCCESS
;               CY = 0
;               Get/Set performed
;           FAIL
;               CY = 1
;               AX = error code
;
;           HARD ERROR
;               CY = 1
;               AX = 0FFFFh
;
;       CONTEXT
;           Called from Virtual Mode
;           Executes in Kernel
;
;       STEPS
;           get registers
;           map segment
;           call GSetMediaID
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;           demMapDS
;           GSetMediaID
;
;       USES
;           EAX,EBX,ECX,EDX,ESI,EDI,DS,ES
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,GS:NOTHING,FS:NOTHING
        align   4

Procedure demGSetMediaID,near
        mov     eax,[ebx].vsf_eax
        mov     ecx,[ebx].vsf_ecx
        push    [ebx].vsf_ebx           ; save user's bx
        call    demMapDSDX
        assume  ds:nothing
        pop     ebx                     ; get user's bx
        CALL16  GSetMediaID
        ret
EndProc   demGSetMediaID
SWAP32_28 ends

SWAP32_22 segment
;***    demGeneric - route selected OS/2 apis to workers
;
;       demGeneric calls selected OS/2 workers to perform services for
;       OS/2 utilities via utilapi.
;
;       ENTRY
;           VSF(BX)
;               ordinal (see ordinals.inc)
;           VSF(CX)
;               signature (636Ch or 'cl')
;           VSF(DS)
;               callers data segment (Ignored if BX is 0)
;           VSF(ES:DI)
;               stack frame (Interpreted if BX is 0 as per DX)
;           VSF(DX)
;               subfunction for BX=0
;                   1 = Title Set notification (ES:DI is new title)
;                   2 = Title Reset notification
;                   Change MAX_GEN_SUBFUNC below on adding new sub function
;                   4 = Get the PTDS's JFT length                       ;BN001;
;
;       EXIT
;           SUCCESS
;               CY = 0
;           FAIL
;               CY = 1
;               AX = error code
;
;       USES
;           EAX,EBX,ECX,EDX,ESI,EDI,DS,ES
;
;       NOTES
;           This function is also being used for putting the titles
;           on windowed VDMs. In such a case ordinal number used (BX)
;           will be zero. Callers data segment and stack frame parmaeters
;           are not used. As this ordinal may be used in future for
;           some other purposes of MVDM, DX will tell the subfunction.
;
;           For now we use compare-jmp because there are only a few
;           valid ordinals. In the future this could be changed to a
;           jmp table.
;
;           This routine makes the assumption that all pointers passed
;           on the the stack have DS as their segment value.  This is
;           to simplify changing them to selectors.
;
;

;MAX_GEN_SUBFUNC     EQU     4                                          ;BD001;

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

Procedure demGeneric,near
        movzx   eax,[ebx].vsf_bx
        or      eax,eax
        jz      generic_bx_0

;------ BX=ordinal values
        call    demMapESDI
        assume  es:NOTHING
        call    demMapDS
        assume  ds:NOTHING

        .if     <eax eq ORD_DOS32STARTSESSION>        ;=37              ;26159;
          call    demStartSession                                       ;26159;
        .elseif <eax eq ORD_DOSGETCP>                 ;=130             ;26159;
          ;DOS Entry: AH=64h                                            ;BN009;
          ;           BX=0082h                                          ;BN009;
          ;           CX=636Ch                                          ;BN009;
          ;           DS:DI=&buffer  returns buffer[0]=length           ;BN009;
          ;           DX=length                                         ;BN009;
          movzx   ebx,dx                                                ;BN009;
          inc     di                                                    ;BN009;
          inc     di                                                    ;BN009;
          CALL16  w_GetCp                                               ;BN009;
          dec     di                                                    ;BN009;
          dec     di                                                    ;BN009;
          mov     ds:[di],cx                                            ;BN009;
        .elseif <eax eq ORD_DOSQFSATTACH>             ;=167             ;BC003;
          call    demQFSAttach
        .elseif <eax eq ORD_DOSEDITNAME>              ;=191             ;BC003;
          call    demEditName
        .elseif <eax eq ORD_DOS32CREATEEVENTSEM>      ;=324
          lea     eax,_VR32CreateEventSem
          call    demCreateSem
        .elseif <eax eq ORD_DOS32OPENEVENTSEM>        ;=325
          lea     eax,_VR32OpenEventSem
          call    demOpenSem
        .elseif <eax eq ORD_DOS32CLOSEEVENTSEM>       ;=326
          lea     eax,_VR32CloseEventSem
          call    demCloseSem
        .elseif <eax eq ORD_DOS32RESETEVENTSEM>       ;=327
          lea     eax,_VR32ResetEventSem
          call    demResetSem
        .elseif <eax eq ORD_DOS32POSTEVENTSEM>        ;=328
          lea     eax,_VR32PostEventSem
          call    demCloseSem
        .elseif <eax eq ORD_DOS32WAITEVENTSEM>        ;=329
          lea     eax,_VR32WaitEventSem
          call    demWaitSem
        .elseif <eax eq ORD_DOS32QUERYEVENTSEM>       ;=330
          lea     eax,_VR32QueryEventSem
          call    demResetSem
        .elseif <eax eq ORD_DOS32CREATEMUTEXSEM>      ;=331
          lea     eax,_VR32CreateMutexSem
          call    demCreateSem
        .elseif <eax eq ORD_DOS32OPENMUTEXSEM>        ;=332
          lea     eax,_VR32OpenMutexSem
          call    demOpenSem
        .elseif <eax eq ORD_DOS32CLOSEMUTEXSEM>       ;=333
          lea     eax,_VR32CloseMutexSem
          call    demCloseSem
        .elseif <eax eq ORD_DOS32REQUESTMUTEXSEM>     ;=334
          lea     eax,_VR32RequestMutexSem
          call    demWaitSem
        .elseif <eax eq ORD_DOS32RELEASEMUTEXSEM>     ;=335
          lea     eax,_VR32ReleaseMutexSem
          call    demCloseSem
        .elseif <eax eq ORD_DOS32QUERYMUTEXSEM>       ;=336
          call    demQueryMutexSem
        .elseif <eax eq ORD_DOS32CREATEMUXWAITSEM>    ;=337
          call    demCreateMuxWaitSem
        .elseif <eax eq ORD_DOS32OPENMUXWAITSEM>      ;=338
          lea     eax,_VR32OpenMuxWaitSem
          call    demOpenSem
        .elseif <eax eq ORD_DOS32CLOSEMUXWAITSEM>     ;=339
          lea     eax,_VR32CloseMuxWaitSem
          call    demCloseSem
        .elseif <eax eq ORD_DOS32WAITMUXWAITSEM>      ;=340
          lea     eax,_VR32WaitMuxWaitSem
          call    demWaitMuxWaitSem
        .elseif <eax eq ORD_DOS32ADDMUXWAITSEM>       ;=341
          lea     eax,_VR32AddMuxWaitSem
          call    demResetSem
        .elseif <eax eq ORD_DOS32DELETEMUXWAITSEM>    ;=342
          call    demDeleteMuxWaitSem
        .elseif <eax eq ORD_DOS32QUERYMUXWAITSEM>     ;=343
          call    demQueryMuxWaitSem
        .elseif <eax eq ORD_DOSFORCEDELETE>           ;=203
          ;DOS Entry: AH=64h
          ;           BX=00CBh
          ;           CX=636Ch
          ;           DS:DX=&asciiz
          CALL16  w_Unlink
          .if     nc
            xor     ax,ax
          .endif

        .elseif <eax eq ORD_DOS32SHUTDOWN>    ;415                      ;125881
          xor     ecx,ecx                                               ;125881
          mov     edi,ecx                                               ;125881
          movzx   esi,al                                                ;125881
          CALL16  w_Shutdown                                            ;125881

        .else
          jmp           gnk20
        .endif

        cmp     ax,1                    ; check for an error
        cmc
        ret

;------ BX=0, special requests

generic_bx_0:

        movzx   edx,[ebx].vsf_dx

        .if     <EDX eq 1>
          ; Set Title Notification
          ; Entry:  VSF(ES:DI) = VDM Title
          call    demGetLin
          CCALL32 vdmmSetTitle <eax>
        .elseif <EDX eq 2>
          ; Get Old Title
          ; Entry: VSF(ES:DI) = Place where old VDM Title will be placed
          call    demGetLin
          CCALL32 vdmmGetTitle <eax>
        .elseif <EDX eq 4>
          mov     ax,ss:[JFN_Length]    ;=function 4                    ;BN001;
        .elseif <EDX eq 5>                                              ;BN007;
          movzx   ebx,[ebx].vsf_di                                      ;BN007;
          CALL16  SFFromHandle                    ; get the SF entry    ;BN007;
          mov     ax,es:[di].sf_flags2                                  ;BN007;
IFDEF PMDEBUG                                                           ;BN012;
        .elseif <EDX eq 6>                                              ;BN012;
          ;Replace the DOSKRNL.SYM symbols with another symbol file.    ;BN012;
          ;AH=64h                                                       ;BN012;
          ;BX=0                                                         ;BN012;
          ;CX=636Ch                                                     ;BN012;
          ;DX=6                                                         ;BN012;
          ;DS=base segment address                                      ;BN012;
          ;ES:DI=&symbol file to load                                   ;BN012;
          ;-------                                                      ;BN012;
          EXTRN   _DebugFreeSymV86Krnl:near                             ;BN012;
          EXTRN   _DebugLoadSymV86Krnl:near                             ;BN012;
          call    _DebugFreeSymV86Krnl                                  ;BN012;
          movzx   eax,[ebx].vsf_ds    ;DS=base segment address          ;BN012;
          push    eax                                                   ;BN012;
          movzx   eax,[ebx].vsf_es    ;ES:DI=&asciiz name               ;BN012;
          movzx   edx,[ebx].vsf_di                                      ;BN012;
          shl     eax,4                                                 ;BN012;
          add     eax,edx                                               ;BN012;
          push    eax                                                   ;BN012;
          call    _DebugLoadSymV86Krnl                                  ;BN012;
ENDIF ;PMDEBUG                                                          ;BN012;
        .elseif <EDX eq 7>
          movzx   eax,CallGate_Debug_SymWinOS2
        .elseif <EDX eq 9>                                              ;70592;
          movzx   eax,[ebx].vsf_al                                      ;70592;
          CALL16  Find_VPB              ; es:di -> vpb                  ;70592;
          jc      gnk20                                                 ;70592;
          LES     DI,es:[di].vpb_fsi.vpi_pDPB                           ;70592;
          movzx   eax,es:[di].dpb_drive_lock                            ;70592;
        .else
gnk20:
          mov     eax,ERROR_INVALID_FUNCTION
          stc
          ret
        .endif
        clc
        ret

EndProc   demGeneric
SWAP32_22 ends

;***    DemStartSession - start a new OS/2 session                      ;26159;
;                                                                       ;26159;
;                                                                       ;26159;
;       ENTRY                                                           ;26159;
;           VSF(DS:SI)                                                  ;26159;
;               Start data structure                                    ;26159;
;                                                                       ;26159;
;       EXIT                                                            ;26159;
;           VSF(AX) rc                                                  ;26159;
;           VSF(BX) pid                                                 ;26159;
;           VSF(CX) sid                                                 ;26159;
;                                                                       ;26159;
;       USES                                                            ;26159;
;                                                                       ;26159;
                                                                        ;26159;
.demSS_zero_Dword macro                                                 ;26159;
        lodsd                                                           ;26159;
        or      eax,eax                                                 ;26159;
        jnz     DemSS_bad                                               ;26159;
        stosd                                                           ;26159;
        endm                                                            ;26159;
                                                                        ;26159;
                                                                        ;26159;
        ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING,GS:NOTHING,FS:NOTHING  ;26159;
        align   4                                                       ;26159;
                                                                        ;26159;
Procedure demStartSession,near                                          ;26159;
                                                                        ;26159;
        FlatContext <ds,es>,eax                                         ;26159;
        assume  ES:FLAT,DS:FLAT                                         ;26159;

;------ setup sync values in case of multiple blocks on wait below      ;65622;
        cli                                                             ;65622;
        mov     eax,[_demSS_next]                                       ;65622;
        mov     [_demSS_us],eax                                         ;65622;
        inc     eax                                                     ;65622;
        mov     [_demSS_next],eax                                       ;65622;
        sti                                                             ;65622;
                                                                        ;65622;
;------ Block waiting for EventSem and sync number to match             ;65622;
        .repeat                                                         ;65622;
                                                                        ;65622;
          ;------ DosWaitEventSem( demVDMStartDoneHndl, timeout)        ;65622;
          push    10000  ;-1=forever  ;10 seconds = 10,000 milliseconds ;65622;
          push    [_demVDMStartDoneHndl]                                ;65622;
          sub     esp,SIZETHUNKSEF                                      ;65622;
          call    _VR32WaitEventSem                                     ;65622;
          add     esp,SIZETHUNKSEF+(4*2)                                ;65622;
                                                                        ;65622;
          mov     eax,[_demSS_us]                                       ;65622;
        .until  <[_demSS_curr] eq eax>                                  ;65622;
                                                                        ;65622;
;------ DosResetEventSem( demVDMStartDoneHndl, &count )                 ;65622;
        push    offset FLAT:_demVDMStartCount                           ;65622;
        push    [_demVDMStartDoneHndl]                                  ;65622;
        sub     esp,SIZETHUNKSEF                                        ;65622;
        call    _VR32ResetEventSem                                      ;65622;
        add     esp,SIZETHUNKSEF+(4*2)                                  ;65622;
                                                                        ;26159;
;------ translate data from v86mode to MVDM status data area            ;26159;
        cld                                                             ;26159;
                                                                        ;70592;
;------ setup current drive and sub-directory information               ;70592;
        mov     eax,offset FLAT:_demStartSession_CDS_lowmem             ;70592;
        xor     edx,edx                                                 ;70592;
        .errnz  ISELDEMTEMP                                             ;70592;
        push    es                                                      ;70592;
        push    ds                                                      ;70592;
        push    ebx                                                     ;70592;
        push    eax                                                     ;70592;
        mov     dword ptr [eax],"\:" shl 8      ;00 ":" "\" 00          ;70592;
        mov     ecx,68                                                  ;70592;
        push    ecx                                                     ;70592;
        ;entry: eax=linear address                                      ;70592;
        ;       ecx=size                                                ;70592;
        ;       edx=index of selector                                   ;70592;
        call    demMapVirt              ;mvdm\demfile2.asm              ;70592;
        ;exit:  NC, AX=selector                                         ;70592;
        pop     ecx                                                     ;70592;
        .if     nc                                                      ;70592;
          mov     ebx,eax                                               ;70592;
          mov     esi,3                                                 ;70592;
          xor     edx,edx                                               ;70592;
          ;entry: BX:SI=&buffer                                         ;70592;
          ;       CX=size                                               ;70592;
          ;       DL=drive number                                       ;70592;
          CALL16  w_Current_Dir         ;filesys\path.asm               ;70592;
          ;exit:  NC=ok                                                 ;70592;
          assume  ds:nothing,es:nothing                                 ;70592;
        .endif                                                          ;70592;
        pop     esi                                                     ;70592;
        pop     ebx                                                     ;70592;
        pop     ds                                                      ;70592;
        pop     es                                                      ;70592;
        assume  DS:FLAT,ES:FLAT                                         ;70592;
        mov     ecx,68/4                ;copy from low to high CDS      ;70592;
        mov     edi,offset FLAT:_demStartSession_CDS                    ;70592;
        mov     al,ss:[LCurDrv]                                         ;70592;
        mov     [_demStartSession_data].demSS_DemCurrentDirectory,edi   ;70592;
        mov     [_demStartSession_data].demSS_DemCurrent_drive,al       ;70592;
        .if     nc                      ;w_Current_Dir fail?            ;70592;
          add     al,'A'                                                ;70592;
          mov     [esi],al                                              ;70592;
        .endif                                                          ;70592;
        rep     movsd                                                   ;70592;
        SaveReg <eax, ecx, edi>                                         ;74035;
        mov   edi,offset FLAT:_demStartSession_CDS                      ;74035;
        mov   ecx,68                  ;length of _demStartSession_CDS   ;74035
        mov   eax,CD_LOCAL            ;Flag for Substitution            ;74035;
        call  demSubstPhys            ;get physical path if drive subst ;74035;
        RestoreReg <edi, ecx, eax>                                      ;74035;
        mov     al,ss:[Cons_Loc].Scrn_Num                               ;70592;
        mov     [_demStartSession_data].demSS_DemScreen_group,al        ;70592;

;------
        movzx   esi,[ebx].vsf_ds                                        ;26159;
        shl     esi,4                                                   ;26159;
        movzx   edi,[ebx].vsf_si                                        ;26159;
        add     esi,edi                                                 ;26159;
        mov     edi,offset FLAT:_demStartSession_data.demSS_Length      ;26159;

        lodsw                           ;length                         ;26159;
        cmp     ax,24                                                   ;26159;
        je      DemSS_SizeOk                                            ;26159;
        cmp     ax,30                                                   ;26159;
        je      DemSS_SizeOk                                            ;26159;
        cmp     ax,32                                                   ;26159;
        je      DemSS_SizeOk                                            ;26159;
        cmp     ax,50                                                   ;26159;
        je      DemSS_SizeOk                                            ;26159;
        cmp     ax,60                                                   ;26159;
        jne     DemSS_bad                                               ;26159;
DemSS_SizeOk:                                                           ;26159;
        stosw                                                           ;26159;
                                                                        ;26159;
;65622; .demSS_zero_word                                                ;65622;
        lodsw                           ;related, must be 0 or 1        ;65622;
        cmp     ax,1                                                    ;65622;
        ja      DemSS_bad                                               ;65622;
        stosw                                                           ;65622;
                                                                        ;26159;
        lodsw                           ;FgBg, must be 0 or 1           ;26159;
        cmp     ax,1                                                    ;26159;
        ja      DemSS_bad                                               ;26159;
        stosw                                                           ;26159;
                                                                        ;26159;
;65622; .demSS_zero_word                                                ;26159;
        lodsw                           ;TraceOpt, must be 0, 1 or 2    ;65622;
        cmp     ax,2                                                    ;65622;
        ja      DemSS_bad                                               ;65622;
        stosw                                                           ;65622;
                                                                        ;26159;
        lodsd                           ;PgmTitle                       ;26159;
        or      eax,eax                                                 ;26159;
        .if     nz                                                      ;26159;
          mov   edx,offset FLAT:_demStartSession_data.demSS_DataPgmTitle;26159;
          mov   ecx,DemSS_PgmTitle_size                                 ;26159;
          call  demMoveConvert                                          ;26159;
        .endif                                                          ;26159;
        stosd                                                           ;26159;
                                                                        ;26159;
        lodsd                           ;PgmName                        ;26159;
        or      eax,eax                                                 ;26159;
        .if     nz                                                      ;26159;
          mov   edx,offset FLAT:_demStartSession_data.demSS_DataPgmName ;26159;
          mov   ecx,DemSS_PgmName_size                                  ;26159;
          call  demMoveConvert                                          ;26159;
          SaveReg <eax, ecx, edi>                                       ;74035;
          mov   edi,offset FLAT:_demStartSession_data.demSS_DataPgmName ;74035;
          mov   ecx,DemSS_PgmName_size                                  ;74035;
          mov   eax,CD_LOCAL            ;Find Substitution              ;74035;
          call  demSubstPhys            ;get physical path if subst     ;74035;
          RestoreReg <edi, ecx, eax>                                    ;74035;
        .endif                                                          ;26159;
        stosd                                                           ;26159;
                                                                        ;26159;
        lodsd                           ;PgmInputs                      ;26159;
        or      eax,eax                                                 ;26159;
        .if     nz                                                      ;26159;
          mov  edx,offset FLAT:_demStartSession_data.demSS_DataPgmInputs;26159;
          mov  ecx,DemSS_PgmInputs_size                                 ;26159;
          call demMoveConvert                                           ;26159;
        .endif                                                          ;26159;
        stosd                                                           ;26159;
                                                                        ;26159;
        .demSS_zero_Dword               ;TermQ, must be 0               ;26159;
                                                                        ;26159;
        cmp     [_demStartSession_data].demSS_Length,18h ;24            ;26159;
        je      demSS_done                                              ;26159;
                                                                        ;26159;
;65622; .demSS_zero_Dword                                               ;65622;
        lodsd                           ;environment                    ;65622;
        or      eax,eax                                                 ;65622;
        .if     nz                                                      ;65622;
          mov  edx,offset FLAT:_demStartSession_data.demSS_DataEnv      ;65622;
          mov  ecx,DemSS_Env_size                                       ;65622;
          call demMoveConvert                                           ;65622;
        .endif                                                          ;65622;
        stosd                                                           ;65622;
                                                                        ;26159;
;65622; .demSS_zero_word                                                ;65622;
        lodsw                           ;InheritOpt, must be 0 or 1     ;65622;
        cmp     ax,1                                                    ;65622;
        ja      DemSS_bad                                               ;65622;
        stosw                                                           ;65622;
                                                                        ;26159;
        .if     <<[_demStartSession_data].demSS_Length> ne 1Eh> ;30     ;26159;
                                                                        ;26159;
          lodsw                         ;SessionType, must be 0..9      ;26159;
          cmp     ax,9                                                  ;26159;
          ja      DemSS_bad                                             ;26159;
          stosw                                                         ;26159;
                                                                        ;26159;
          .if     <<[_demStartSession_data].demSS_Length> ne 20h> ;32   ;26159;
                                                                        ;26159;
            lodsd                       ;IconFile                       ;26159;
            or      eax,eax                                             ;26159;
            .if     nz                                                  ;26159;
              mov     edx,offset FLAT:_demStartSession_data.demSS_DataIconFile
              mov     ecx,DemSS_PgmInputs_size                          ;26159;
              call    demMoveConvert                                    ;26159;
            .endif                                                      ;26159;
            stosd                                                       ;26159;
                                                                        ;26159;
            .demSS_zero_Dword           ;PgmHandle, must be 0           ;26159;
                                                                        ;26159;
            lodsw                       ;PgmControl,bits 4..14 must be 0;26159;
            test    ax,7FF0h                                            ;26159;
            jnz     DemSS_bad                                           ;26159;
            stosw                                                       ;26159;
                                                                        ;26159;
            movsd                       ;InitXYPos                      ;26159;
            movsd                       ;InitXYSize                     ;26159;
                                                                        ;26159;
            .if     <<[_demStartSession_data].demSS_Length> ne 32h> ;50 ;26159;
                                                                        ;26159;
              lodsw                     ;reserved, must be 0            ;26159;
              or      ax,ax                                             ;26159;
              jnz     DemSS_bad                                         ;26159;
              stosw                                                     ;26159;
                                                                        ;26159;
              .demSS_zero_Dword         ;ObjectBuffer, must be 0        ;26159;
              .demSS_zero_Dword         ;ObjectBufferLen, must be 0     ;26159;
                                                                        ;26159;
            .endif                                                      ;26159;
          .endif                                                        ;26159;
        .endif                                                          ;26159;
demSS_done:                                                             ;26159;
                                                                        ;26159;
                                                                        ;26159;
;------ SysServ Wakeup                                                  ;26159;
        push    ebx                                                     ;26159;
;       ENTRY   (BX) = Daemon function number                           ;26159;
;               (SI) = Offset of queue (queue must be in DOSGROUP)      ;26159;
;               (AX) = Event datum1 to queue                            ;26159;
        mov     eax,offset FLAT:_demStartSession_data                   ;26159;
        push    eax                                                     ;26159;
        mov     bx,SysServ_VDMSta       ; Session manager function      ;26159;
        mov     si,offset DOSGROUP:SMDosSessionQ                        ;26159;
        CALL16  SysServQueueEvent       ;task\SysServ.asm               ;26159;
        pop     eax                                                     ;26159;
        ror     eax,10h                                                 ;26159;
        mov     bx,SysServ_VDMSta       ; Session manager function      ;26159;
        mov     si,offset DOSGROUP:SMDosSessionQ                        ;26159;
        CALL16  SysServQueueEvent       ;task\SysServ.asm               ;26159;
;       EXIT    Carry set                                               ;26159;
;                   No daemon                                           ;26159;
;               Carry clear                                             ;26159;
;                   No error                                            ;26159;
        pop     ebx                                                     ;26159;
        FlatContext <es,ds>,eax                                         ;26159;
        assume  ES:FLAT,DS:FLAT                                         ;26159;
                                                                        ;26159;
;------ return data to V86 user                                         ;26159;
        xor     eax,eax                                                 ;65622;
DemSS_ret:                                                              ;26159;
                                                                        ;65622;
;------ release the next blocked event semaphore                        ;65622;
        inc     [_demSS_curr]                                           ;65622;
                                                                        ;65622;
;------ return code                                                     ;26159;
        mov     [ebx].vsf_ax,ax                                         ;26159;
        ret                                                             ;26159;
                                                                        ;26159;
DemSS_bad:                                                              ;26159;
        mov     ax,ERROR_INVALID_PARAMETER                              ;26159;
        jmp     DemSS_ret                                               ;26159;
EndProc   demStartSession                                               ;26159;
                                                                        ;26159;
        ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING,GS:NOTHING,FS:NOTHING  ;26159;
        align   4                                                       ;26159;
Procedure demMoveConvert,near                                           ;26159;
;Entry: edx=&target data location (flat)                                ;26159;
;       eax=&source data location (segment:offset)                      ;26159;
;       ecx=size of data                                                ;26159;
                                                                        ;26159;
        push    edi                                                     ;26159;
        push    esi                                                     ;26159;
                                                                        ;26159;
        xchg    eax,edx                                                 ;26159;
        mov     edi,eax                                                 ;26159;
        sub     eax,offset FLAT:_demStartSession_data                   ;26159;
        movzx   esi,dx                                                  ;26159;
        shr     edx,10h                                                 ;26159;
        shl     edx,4                                                   ;26159;
        add     esi,edx                                                 ;26159;
;esi=&source (flat)                                                     ;26159;
;edi=&target (flat)                                                     ;26159;
        rep     movsb                                                   ;26159;
                                                                        ;26159;
        pop     esi                                                     ;26159;
        pop     edi                                                     ;26159;
        ret                                                             ;26159;
EndProc   demMoveConvert                                                ;26159;
                                                                        ;26159;
                                                                        ;26159;
SWAP32_26 segment
;***    demSetTitle - Set VDM Title
;
;
;       ENTRY
;           VSF(ES:DI)
;               VDM Title
;
;       EXIT
;           None
;
;       USES
;           EDI
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,GS:NOTHING,FS:NOTHING
        align   4

Procedure demSetTitle,near
        call    demGetLin
        CCALL32 vdmmSetTitle <eax>
        ret
EndProc   demSetTitle
SWAP32_26 ends


;***    demQFSAttach - V86 mode entrance to w_qFSAttach worker
;
;       Performs setup and call to OS/2 workers to perform services for
;       DOSQFSAttach.
;
;       ENTRY
;           DS
;               callers data segment
;           ES:DI
;               stack frame
;
;       EXIT
;           SUCCESS
;               CY = 0
;           FAIL
;               CY = 1
;               AX = error code
;
;       USES
;           EAX,EBX,ECX,EDX,ESI,EDI,DS,ES
;
        ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING,GS:NOTHING,FS:NOTHING

Procedure demQFSAttach,near

LocalVar FSQA_argframe, <size FSQAttachStruc>   ; arg frame on kernel stack
;80511; LocalVar FSQA_pDOSretnsize, DWORD       ;80511

        EnterProc

;       Copy argument frame from callers stack to OS/2 kernel stack

        mov     eax,ds                          ; (EAX) = DS
;80511; mov     FSQA_pDOSretnsize,edi       ;80511
;80511; mov     FSQA_pDOSretnsize.Segmt,ax  ;80511
        push    es
        pop     ds
        movzx   esi,di                          ; (DS:ESI) -> callers arg frame
        push    ss
        pop     es
        lea     edi,[FSQA_argframe]             ; (ES:EDI) -> OS/2 arg frame
        mov     ecx,FSQA_ArgWords               ; frame size
        rep movsw                               ; copy args to OS/2 arg frame

;       Change arg pointers from segments to selectors

        mov     FSQA_argframe.FSQA_cbDataLength.Segmt,ax
        mov     FSQA_argframe.FSQA_pDataBuffer.Segmt,ax
        mov     FSQA_argframe.FSQA_szDeviceName.Segmt,ax

;       Set up registers

        mov     ax,FSQA_argframe.FSQA_iFSAInfoLevl ; (AX) = infolevel
        lds     si,FSQA_argframe.FSQA_szDeviceName ; (DS:SI) -> device name
        lea     ebx,[FSQA_argframe]
        CALL16  w_qFSAttach                     ; go do actual work
;80511;
;80511; push    eax
;80511; push    ds
;80511; push    si
;80511; movzx   eax,word ptr FSQA_argframe.FSQA_cbDataLength
;80511; lds     si,FSQA_pDOSretnsize
;80511; mov     [si].FSQA_cbDataLength,eax
;80511; pop     si
;80511; pop     ds
;80511; pop     eax
;80511;
        LeaveProc
        ret
EndProc   demQFSAttach

;***    demEditName - V86 mode entrance to w_EditName worker
;
;       Performs setup and call to OS/2 worker for 3xb DosEditName service
;
;       ENTRY
;           DS
;               callers data segment
;           ES:DI
;               stack frame
;
;       EXIT
;           SUCCESS
;               CY = 0
;           FAIL
;               CY = 1
;               AX = error code
;
;       USES
;           EAX,EBX,ECX,EDX,ESI,EDI,DS,ES
;
        ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING,GS:NOTHING,FS:NOTHING

EName_argframe  struc
        TgtBufLen       dw  ?           ; target string buffer length
        TgtBuf          dd  ?           ; target buffer
        EdtStr          dd  ?           ; edit string
        SrcStr          dd  ?           ; source string
        EditLevel       dw  ?           ; edit level
EName_argframe  ends

Procedure demEditName,NEAR
        mov     cx,[di].TgtBufLen       ; (CX) = target bufer length
        mov     bx,[di].EditLevel       ; (BX) = edit level
        mov     dx,[di].TgtBuf.Offst    ; (AX:DX) -> user buffer
        mov     si,[di].EdtStr.Offst    ; (DS:SI) -> destination name
        mov     di,[di].SrcStr.Offst    ; (ES:DI) -> source name
        mov     ax,ds                   ; (AX) = selector for user buffer
        mov     es,ax                   ; (ES) = selector for source name
        CALL16  w_EditName              ; go do actual work
        ret
EndProc demEditName

;----------------------------------------------------------------------
;-----------------------
;
; *** Dos32CreateEventSem API ***
;
;-----------------------
; AH=64h
; BX=0144h=ordinal
; CX=636Ch
;
; ES:DI=&asciiz name
; DS:SI=&handle
; DX=attribute (lower 16 bits, upper 16 bits are assumed to be zero)
; AL=state (TRUE or FALSE)
;-----------------------
;-----------------------
;
; *** Dos32CreateMutexSem API ***
;
;-----------------------
; AH=64h
; BX=014Bh=ordinal
; CX=636Ch
;
; ES:DI=&asciiz name
; DS:SI=&handle
; DX=attribute (lower 16 bits, upper 16 bits are assumed to be zero)
; AL=state (TRUE or FALSE)
;-----------------------
;

        assume  ds:nothing,es:nothing,SS:NOTHING,GS:NOTHING,FS:NOTHING
        align   4
Procedure demCreateSem,NEAR

        push    ebp
        mov     ebp,esp
        push    eax

        FlatContext <ds>,eax
        assume  DS:FLAT

        movzx   eax,[ebx].vsf_al        ;\    state
        push    eax                     ;/

        movzx   eax,[ebx].vsf_dx        ;\    attri
        push    eax                     ;/

demSem_DsSi:
        movzx   eax,[ebx].vsf_ds        ;\
        movzx   edx,[ebx].vsf_si        ; \
        shl     eax,4                   ;  >  &handle
        add     eax,edx                 ; /
        push    eax                     ;/

        movzx   eax,[ebx].vsf_es        ;\
        movzx   edx,[ebx].vsf_di        ; \
        shl     eax,4                   ;  >  &asciiz
        add     eax,edx                 ; /
        push    eax                     ;/

        push    ds
        pop     es
        assume  ES:FLAT

demSem:
        sub     esp,SIZETHUNKSEF
        call    [ebp-4]
        mov     esp,ebp
        pop     ebp
        ret

EndProc demCreateSem

;----------------------------------------------------------------------
;
; *** Dos32CreateMuxWaitSem API ***
;
;-----------------------
; AH=64h
; BX=0151h=ordinal
; CX=636Ch
;-----------------------
;

        assume  ds:nothing,es:nothing,SS:NOTHING,GS:NOTHING,FS:NOTHING
        align   4
Procedure demCreateMuxWaitSem,NEAR

demQueryMutexSem:
demDeleteMuxWaitSem:
demQueryMuxWaitSem:

        mov     eax,1   ;error, unsupported function
        ret

EndProc demCreateMuxWaitSem

;----------------------------------------------------------------------
;-----------------------
;
; *** Dos32OpenEventSem API ***
;
;-----------------------
; AH=64h
; BX=0145h=ordinal
; CX=636Ch
;
; ES:DI=&asciiz name
; DS:SI=&handle
;-----------------------
;-----------------------
;
; *** Dos32OpenMuxWaitSem API ***
;
;-----------------------
; AH=64h
; BX=0152h=ordinal
; CX=636Ch
;
; ES:DI=&asciiz name
; DS:SI=&handle
;-----------------------
;-----------------------
;
; *** Dos32OpenMutexSem API ***
;
;-----------------------
; AH=64h
; BX=014Ch=ordinal
; CX=636Ch
;
; ES:DI=&asciiz name
; DS:SI=&handle
;-----------------------
;

SWAP32_23 segment

        assume  ds:nothing,es:nothing,SS:NOTHING,GS:NOTHING,FS:NOTHING
        align   4
Procedure demOpenSem,NEAR

        push    ebp
        mov     ebp,esp
        push    eax

        FlatContext <ds>,eax
        assume  DS:FLAT

        jmp     demSem_DsSi


public  DEM32OPENEVENTSEM
DEM32OPENEVENTSEM:
        pop     eax                     ;retn addr
        pop     ecx                     ;handle
        pop     edx                     ;asciiz

        push    eax                     ;retn addr
        push    ecx
        push    edx

        sub     esp,SIZETHUNKSEF
        call    _VR32OpenEventSem
        add     esp,SIZETHUNKSEF+(4*2)
        ret

EndProc demOpenSem
SWAP32_23 ends


;----------------------------------------------------------------------
;-----------------------
;
; *** Dos32CloseEventSem API ***
;
;-----------------------
; AH=64h
; BX=0146h=ordinal
; CX=636Ch
;
; DX:SI=handle (32-bit value)
;-----------------------
;-----------------------
;
; *** Dos32PostEventSem API ***
;
;-----------------------
; AH=64h
; BX=0148h=ordinal
; CX=636Ch
;
; DX:SI=handle (32-bit value)
;-----------------------
;-----------------------
;
; *** Dos32ReleaseMutexSem API ***
;
;-----------------------
; AH=64h
; BX=014Fh=ordinal
; CX=636Ch
;
; DX:SI=handle (32-bit value)
;-----------------------
;-----------------------
;
; *** Dos32CloseMuxWaitSem API ***
;
;-----------------------
; AH=64h
; BX=0153h=ordinal
; CX=636Ch
;
; DX:SI=handle
;-----------------------
;-----------------------
;
; *** Dos32CloseMutexSem API ***
;
;-----------------------
; AH=64h
; BX=014Dh=ordinal
; CX=636Ch
;
; DX:SI=handle (32-bit value)
;-----------------------
;

SWAP32_27 segment
        assume  ds:nothing,es:nothing,SS:NOTHING,GS:NOTHING,FS:NOTHING
        align   4
Procedure demCloseSem,NEAR

        push    ebp
        mov     ebp,esp
        push    eax

        FlatContext <ds>,eax
        assume  DS:FLAT

demSem_handle:
        mov     ax,[ebx].vsf_dx         ;\
        ror     eax,16                  ; \  handle
        mov     ax,[ebx].vsf_si         ; /
        push    eax                     ;/

        push    ds
        pop     es
        assume  ES:FLAT

        jmp     demSem


public  DEM32CLOSEEVENTSEM
DEM32CLOSEEVENTSEM:
        pop     eax                     ;retn addr
        pop     ecx                     ;handle

        push    eax                     ;retn addr
        push    ecx                     ;handle

        sub     esp,SIZETHUNKSEF
        call    _VR32CloseEventSem
        add     esp,SIZETHUNKSEF+(4*1)
        ret

EndProc demCloseSem
SWAP32_27 ends

;----------------------------------------------------------------------
;-----------------------
;
; *** Dos32ResetEventSem API ***
;
;-----------------------
; AH=64h
; BX=0147h=ordinal
; CX=636Ch
;
; DX:SI=handle (32-bit value)
; ES:DI=&count
;-----------------------
;-----------------------
;
; *** Dos32QueryEventSem API ***
;
;-----------------------
; AH=64h
; BX=014Ah=ordinal
; CX=636Ch
;
; DX:SI=handle
; ES:DI=&count
;-----------------------
;-----------------------
;
; *** Dos32AddMuxWaitSem API ***
;
;-----------------------
; AH=64h
; BX=0155h=ordinal
; CX=636Ch
;
; DX:SI=handle
; ES:DI=&count
;-----------------------
;

        assume  ds:nothing,es:nothing,SS:NOTHING,GS:NOTHING,FS:NOTHING
        align   4
Procedure demResetSem,NEAR

        push    ebp
        mov     ebp,esp
        push    eax

        FlatContext <ds>,eax
        assume  DS:FLAT

        movzx   eax,[ebx].vsf_es        ;\
        movzx   edx,[ebx].vsf_di        ; \
        shl     eax,4                   ;  >  &count
        add     eax,edx                 ; /
        push    eax                     ;/

        jmp     demSem_handle

EndProc demResetSem

;----------------------------------------------------------------------
;-----------------------
;
; *** Dos32WaitEventSem API ***
;
;-----------------------
; AH=64h
; BX=0149h=ordinal
; CX=636Ch
;
; DX:SI=handle (32-bit value)
; AL=time-out in seconds, 0=none -1=infinite
;-----------------------
;-----------------------
;
; *** Dos32RequestMutexSem API ***
;
;-----------------------
; AH=64h
; BX=014Eh=ordinal
; CX=636Ch
;
; DX:SI=handle (32-bit value)
; AL=time-out in seconds, 0=none -1=infinite
;-----------------------
;

        assume  ds:nothing,es:nothing,SS:NOTHING,GS:NOTHING,FS:NOTHING
        align   4
Procedure demWaitSem,NEAR

        push    ebp
        mov     ebp,esp
        push    eax

        FlatContext <ds>,eax
        assume  DS:FLAT

demSem_timeout:
        movzx   eax,[ebx].vsf_al        ;\
        .if     <AL eq -1>              ; \
          mov     eax,-1                ;  \
        .else                           ;   \ timeout
          mov     edx,1000              ;   /
          mul     edx                   ;  /
        .endif                          ; /
        push    eax                     ;/

        jmp     demSem_handle

EndProc demWaitSem

;----------------------------------------------------------------------
;-----------------------
;
; *** Dos32WaitMuxWaitSem API ***
;
;-----------------------
; AH=64h
; BX=0154h=ordinal
; CX=636Ch
;
; DX:SI=handle
; ES:DI=&user
; AL=time-out in seconds, 0=none -1=infinite
;-----------------------
;

        assume  ds:nothing,es:nothing,SS:NOTHING,GS:NOTHING,FS:NOTHING
        align   4
Procedure demWaitMuxWaitSem,NEAR

        push    ebp
        mov     ebp,esp
        push    eax

        FlatContext <ds>,eax
        assume  DS:FLAT

        movzx   eax,[ebx].vsf_es        ;\
        movzx   edx,[ebx].vsf_di        ; \
        shl     eax,4                   ;  >  &user
        add     eax,edx                 ; /
        push    eax                     ;/

        jmp     demSem_timeout

EndProc demWaitMuxWaitSem
;
;Begin 74035
;----------------------------------------------------------------------
;-----------------------
;
; *** demSubstPhys ***
;
;-----------------------
; ENTRY:
;      AL= CD_LOCAL or CD_JOIN Flag
;      CX= Length of String Buffer
;      EDI= Address of ASCIIZ drive:path(file name)
;-----------------------
; EXIT:
;
; Uses: EAX, ECX, EDI
;
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,GS:NOTHING,FS:NOTHING
        align   4

Procedure demSubstPhys,near

LocalVar substbuf, DemSS_PgmName_size

        EnterProc

        SaveReg <ebx, edx, esi, es, ds, ds>

        mov     edx,edi                    ;save starting address of a string
        call    XCHGP32                    ;ds:si -> string to be substituted

        push    ss
        pop     es

        lea     edi, substbuf            ;buffer for substituted drive

        mov     ebx, 0
        mov     bl, al                   ;CD_LOCAL for substitution or
                                         ;CD_JION  for Join
        mov     ax, 0
        mov     al, BYTE PTR ds:[esi]    ;letter based drive
        sub     al,'A'                   ;make '0' based drive

        push    ecx                      ;save length of buffer
        push    es
        CALL16  ListCDSText              ;Gets substituted directory
        pop     es
        pop     ecx
        RestoreReg <ds>
        jc      lCDSt99

;
; substbuf has substituted directory path (e.g. E:\DAZZLE) if drive is
; substituted
;

        lea     edi, substbuf            ;get substituted drive buffer
        cmp     BYTE PTR es:[edi], 0     ;nz - substitution found
        jz      short lCDSt99            ;Jump if drive is not substituted

;
;Find end of substbuf string
;

        mov     al, 0                    ;delimeter for search
        lea     edi, substbuf            ;load physical CDS path or program
        repne   scasb                    ;search es:di until '0' found
        dec     di                       ;make es:di point to '0'

;
;append ds:esi to substbuf. (strcat subtbuf ds:esi)
;
        mov     esi, edx                 ;restore starting address of string
        cmp     BYTE PTR  ds:[esi+3], 0  ;if zero, it is only a root dir.
        jz      wasrootdir               ;no need to copy.
        inc     esi
        inc     esi                      ;esi pointing to '\'.
loop1:  movsb                            ;copy byte ds:si -> es:di until
        cmp     BYTE PTR ds:[esi], al    ; null found
        jnz     loop1                    ;jump if null found
        mov     BYTE PTR es:[edi], al    ;null end string


wasrootdir:
        call    XCHGP32                  ; ds:si -> substituted string (substbuf)
                                         ; es:di -> string to be substituted

;
;Copy substbuf to es:edi (Entry string)
;

        mov     edi, edx                 ;restore starting address of string
        lea     esi, substbuf            ;load physical directory
loop2:  movsb                            ;copy byte until end of string found
        cmp     BYTE PTR ds:[esi], al    ;
        jnz     loop2                    ;
        mov     BYTE PTR es:[edi], al    ;null end string

lCDSt99:
        RestoreReg <ds, es, esi, edx, ebx>
        LeaveProc
        ret

EndProc demSubstPhys

;
;XCHGP32 is like XCHGP macro in task/subr.asm except this on is for 32 bit.
;Swaps ES:EDI and DS:ESI. ES:EDI -> DS:ESI and DS:ESI -> ES:EDI.
;
Procedure XCHGP32,near

        push    ds
        push    es
        pop     ds
        pop     es
        xchg    edi,esi
        ret

EndProc XCHGP32
;
;End 74035
;
EndCode

        END
