þa‹RþwQþ m^9þhý oPþ nSystem-wide NAME MsCalls ; This Module provides procedure calls interfaces ; for MsDos Calls. ; The control systemType will determine how much of ; this gets assembled. If systemType = 2, then all ; of it will be assembled. If systemType = 1, then ; only the phonelink part will be assembled. If ; systemType = 0, then only the GRiDLink part will ; be assembled. DGROUP GROUP DATA CGROUP GROUP CODE ; These are used for GRiDLink, PhoneLink & General PUBLIC MsDos PUBLIC patched PUBLIC msDosIntOffset, msDosIntSegment PUBLIC MsGetMachineType PUBLIC MsGetDiskXferAddr PUBLIC MsGetCurrentDisk, MsSetCurrentDisk PUBLIC MsDeviceListPtr PUBLIC MsDuplicateFileConn, MsDetach ; These are used for PhoneLink & General %IF (%systemType EQ 1 OR %systemType EQ 2) THEN ( PUBLIC MsKeyPressed, MsCharIn, MsCallDriver ) FI ; These are for General %IF (%systemType EQ 2) THEN ( PUBLIC MsInMsDosPtr, MsAllocate, MsFree, MsAvailableMemory PUBLIC MsCharOut, MsLineOut PUBLIC MsLineIn, MsPrintChar, MsPrintLine PUBLIC MsAttach, MsRead, MsWrite PUBLIC MsSeek, MsRename, MsDelete PUBLIC MsAddDirectory, MsDeleteDirectory PUBLIC MsSetCurrentDirectory, MsGetCurrentDirectory PUBLIC MsFindFirstDirEntry, MsFindNextDirEntry PUBLIC MsChangeAttributes, MsIOControl PUBLIC MsFCBAttach, MsFCBDetach, MsFCBRead, MsFCBWrite, MsFCBRename PUBLIC MsFCBDelete, MsFCBFirstEntry, MsFCBNextEntry PUBLIC MsFCBFileSize, MsFCBSetRelativeRecord, MsFCBParseFileName PUBLIC MsFlushAllDisks, MsSetDiskXferAddr, MsGetDiskFreeSpace PUBLIC MsGetEntrypoint, MsSetCntlCInterrupt PUBLIC MsCreateProcess, MsExit, MsGetExitCode PUBLIC MsTurnCursorOn, MsTurnCursorOff PUBLIC MsGetPDB, MsSetPDB, MsDuplicatePDB ) FI $EJECT ; EQUATES ; file system oldFile EQU 0 ; really 1 updateFile EQU 1 ; really 2 newFile EQU 2 ; really 3 ; general FALSE EQU 0 TRUE EQU 1 fnCallInt EQU 21H ; machine types cpMachine EQU 000H pcMachine EQU 001H noMachine EQU 0FFH ; error codes eOK EQU 0 eMsInvalidParm EQU 1 eMsFileNotFound EQU 2 eMsPathNotFound EQU 3 eMsTooManyOpen EQU 4 eMsAccessDenied EQU 5 eMsInvalidConn EQU 6 eMsMemoryTrashed EQU 7 eMsOutOfMemory EQU 8 eMsInvalidBlock EQU 9 eMsBadEnvironment EQU 10 eMsBadFormat EQU 11 eMsInvalidAccess EQU 12 eMsInvalidData EQU 13 eMsInvalidDrive EQU 15 eMsDirectoryInUse EQU 16 eMsNotSameDevice EQU 17 eMsNoMoreFiles EQU 18 ; These two variables are used only with interceptor ; If left in their initial state; then the following ; routines will work without changes. DATA SEGMENT PUBLIC 'DATA' machineType DB noMachine %IF (%systemType EQ 2) THEN ( cursorOn DB TRUE cursorType DW 0607H cntlCHandlerAddr DW ? DW 50 DUP (?) cntlCStackTop DW ? ) FI DATA ENDS $EJECT CODE SEGMENT PUBLIC 'CODE' ASSUME CS:CGROUP, DS:DGROUP patched DB FALSE msDosIntOffset DW ? msDosIntSegment DW ? ; MsDos: PROCEDURE CLEAN; MsDos PROC NEAR TEST CS:patched, TRUE JNZ MsDosIndirect MsDosInterrupt: INT fnCallInt JMP SHORT MsDosExit MsDosIndirect: PUSHF CALL DWORD PTR CS:msDosIntOffset MsDosExit: RET MsDos ENDP $EJECT ; MsGetDiskXferAddr: PROCEDURE PTR CLEAN; MsGetDiskXferAddr PROC NEAR MOV AH, 2FH CALL MsDos RET ; ES:BX => Disk Xfer Addr MsGetDiskXferAddr ENDP ; MsGetCurrentDisk: PROCEDURE BYTE CLEAN; MsGetCurrentDisk PROC NEAR MOV AH, 19H CALL MsDos RET ; AL = Current disk MsGetCurrentDisk ENDP ; MsSetCurrentDisk: PROCEDURE (drive) BYTE CLEAN; ; DCL drive BYTE; drive EQU BYTE PTR [BP+6] ; parm 2 MsSetCurrentDisk PROC NEAR PUSH DS PUSH BP MOV BP, SP MOV DL, drive MOV AH, 0EH CALL MsDos POP BP ; AL = # logical drives POP DS RET 2 MsSetCurrentDisk ENDP PURGE drive $EJECT FcbType STRUC drive DB 0 fName DB 'NUL ' ext DB ' ' whocares DB 13 DUP (0) pDevEntry DD 0 extra DB 8 DUP (0) FcbType ENDS fcb FcbType <> ; MsDeviceListPtr: PROCEDURE PTR CLEAN; ; ; This routine returns a pointer to the device chain ; MsDeviceListPtr PROC NEAR PUSH DS PUSH BP MOV AH, 30H ; Get DOS version CALL MsDos CMP AL, 3 ; If earlier than version 3.0 JB UseFcbMethod ; then use the Fcb Open (NUL) method CMP AH, 20 ; If earlier than version 3.20 JB UseFcbMethod ; then use the Fcb Open (NUL) method MOV AH, 52H ; Look at MsDos internal variables CALL MsDos LES BX, DWORD PTR ES:[BX+22H] JMP SHORT MsDeviceListReturn UseFcbMethod: XCHG CX, AX ; Save version in CX MOV AH, 0FH ; FCB Open call PUSH CS POP DS MOV DX, OFFSET fcb CALL MsDos ; FCB Open to MsDos MOV BX, 0FFFFH MOV ES, BX MOV BX, 0FH ; Return (NULLPTR) for error case CMP AL, 0FFH JE MsDeviceListReturn CMP CL, 3 JB OlderThanV30 LES BX, fcb.pDevEntry+1 JMP SHORT CloseNulOpen OlderThanV30: LES BX, fcb.pDevEntry ; pointer to nul device CloseNulOpen: MOV AH, 10H CALL MsDos ; close the file. (Close doesn't change ES:BX) MsDeviceListReturn: POP BP POP DS RET MsDeviceListPtr ENDP PURGE fcb PURGE FcbType PURGE drive PURGE fName PURGE ext PURGE whocares PURGE pDevEntry PURGE extra $EJECT ; MsDuplicateFileConn: PROCEDURE (conn, newConn, pError) WORD CLEAN; ; DCL conn WORD; ; DCL newConn WORD; ; DCL pError PTR; pError EQU DWORD PTR [BP+6] ; parm 3 newConn EQU WORD PTR [BP+10] ; parm 2 conn EQU WORD PTR [BP+12] ; parm 1 MsDuplicateFileConn PROC NEAR PUSH DS PUSH BP MOV BP, SP MOV BX, conn MOV CX, newConn CMP CX, 0FFFFH JNE MsDuplicateForce MsDuplicateNormal: MOV AH, 45H CALL MsDos JMP SHORT MsDuplicateExit MsDuplicateForce: MOV AH, 46H CALL MsDos MsDuplicateExit: LDS DI, pError MOV WORD PTR DS:[DI], eOK JNC MsDuplicateFileConnExit MOV DS:[DI], AX ; DS:DI => Error MsDuplicateFileConnExit: ; AX = new conn POP BP POP DS RET 8 MsDuplicateFileConn ENDP PURGE pError, newConn, conn $EJECT ; MsDetach: PROCEDURE (conn, pError) CLEAN; ; DCL conn WORD; ; DCL pError PTR; pError EQU DWORD PTR [BP+6] ; parm 2 conn EQU WORD PTR [BP+10] ; parm 1 MsDetach PROC NEAR PUSH DS PUSH BP MOV BP, SP MOV BX, conn MOV AH, 3EH CALL MsDos LDS DI, pError MOV WORD PTR DS:[DI], eOK JNC MsDetachExit MOV DS:[DI], AX ; DS:DI => Error MsDetachExit: POP BP POP DS RET 6 MsDetach ENDP PURGE pError, conn $EJECT %IF (%systemType EQ 2) THEN ( ; MsCreateProcess: PROCEDURE (pPathname, pParmBlock, pError) CLEAN; ; DCL pPathname PTR ; DCL pParmBlock PTR ; DCL pError PTR pError EQU DWORD PTR [BP+6] ; parm 3 pParmBlock EQU DWORD PTR [BP+10] ; parm 2 pPathname EQU DWORD PTR [BP+14] ; parm 1 usualSS DW ? usualSP DW ? MsCreateProcess PROC NEAR PUSH DS PUSH BP MOV BP, SP LDS DX, pPathname LES BX, pParmBlock ; save the current stack pointer in oldSP and change the stack ; so that SS matches with the PDB (CS-10) of executing program ; This is done to circumvent a bug in IBM PC's loader. ; MOV CS:usualSS, SS MOV CS:usualSP, SP MOV AX, CS SUB AX, 10h MOV SS, AX MOV SP, 100H MOV AX, 4B00H ; mode = load & go ; zzz note for you Tim from Raj & Dan: special for gridmgr. ; cannot use call because stack is screwed upon return from int 21 ; if function is load & go. so need to restore stack immediately upon ; return. INT fnCallInt ; CALL MsDos ; restore the stack MOV SS, CS:usualSS MOV SP, CS:usualSP LDS DI, pError MOV WORD PTR DS:[DI], eOK JNC MsCreateProcessExit MOV DS:[DI], AX ; DS:DI => Error MsCreateProcessExit: POP BP POP DS RET 12 MsCreateProcess ENDP PURGE pError, pParmBlock, pPathname ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsExit: PROCEDURE (exitCode) CLEAN; ; DCL exitCode BYTE exitCode EQU BYTE PTR [BP+4] ; parm 1 MsExit PROC NEAR PUSH BP MOV BP, SP MOV AL, exitCode MOV AH, 4CH CALL MsDos POP BP RET 2 MsExit ENDP PURGE exitCode ; MsGetExitCode: PROCEDURE WORD CLEAN; MsGetExitCode PROC NEAR MOV AH, 4DH CALL MsDos RET MsGetExitCode ENDP ) FI $EJECT %IF (%systemType EQ 1 OR %systemType EQ 2) THEN ( ; MsKeyPressed: PROCEDURE BOOLEAN CLEAN; MsKeyPressed PROC NEAR MOV AH, 0BH CALL MsDos RET MsKeyPressed ENDP ) FI %IF (%systemType EQ 1 OR %systemType EQ 2) THEN ( ; MsCharIn: PROCEDURE BYTE CLEAN; MsCharIn PROC NEAR MOV AH, 07H ; Cntl-C Interrupt Check Disabled CALL MsDos RET MsCharIn ENDP ) FI $EJECT %IF (%systemType EQ 1 OR %systemType EQ 2) THEN ( ; MsCallDriver: PROCEDURE (pDeviceHeader, pRequestBlock) CLEAN; ; DCL pDeviceHeader PTR; ; DCL deviceHeader BASED pDeviceHeader MsDeviceHeaderType; ; ; DCL pRequestBlock PTR; ; DCL requestBlock BASED pRequestBlock MsGenericRequestBlockType; pRequestBlock EQU DWORD PTR [BP+6] ; parm 2 pDeviceHeader EQU DWORD PTR [BP+10] ; parm 1 pEntrypoint EQU DWORD PTR [BP-4] pEntrySeg EQU WORD PTR [BP-2] pEntryOff EQU WORD PTR [BP-4] deviceHeader STRUC nextDevice DD ? attributes DW ? strategyEntryPoint DW ? interruptEntryPoint DW ? deviceHeader ENDS MsCallDriver PROC NEAR PUSH DS PUSH BP MOV BP, SP PUSH AX ; make space for pTemp PUSH AX ; make space for pTemp LES BX, pRequestBlock ; ES:BX => request block LDS SI, pDeviceHeader ; DS:SI => points to deviceHeader MOV AX, DS:[SI].strategyEntryPoint MOV pEntryOff, AX MOV pEntrySeg, DS CALL pEntrypoint ; Need to check error and return MOV AX, DS:[SI].interruptEntryPoint MOV pEntryOff, AX CALL pEntrypoint MOV SP, BP POP BP POP DS RET 8 MsCallDriver ENDP PURGE pEntrypoint, pEntryOff, pEntrySeg PURGE pDeviceHeader, pRequestBlock, deviceHeader PURGE nextDevice, attributes, strategyEntryPoint, interruptEntryPoint ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsCharOut: PROCEDURE (char) CLEAN; ; DCL char BYTE; char EQU BYTE PTR [BP+4] ; parm 1 MsCharOut PROC NEAR PUSH BP MOV BP, SP MOV DL, char CMP DL, 0FFH JE MsCharOutExit MOV AH, 06H ; Cntl-C Interrupt Check Disabled CALL MsDos MsCharOutExit: POP BP RET 2 MsCharOut ENDP PURGE char ; MsLineOut: PROCEDURE (pLineOut) CLEAN; ; DCL pLine PTR; pLineOut EQU DWORD PTR [BP+4] ; parm 1 MsLineOut PROC NEAR PUSH BP MOV BP, SP LES BX, pLineOut MsLineOutLoop: MOV AL, ES:[BX] CMP AL, '$' JE MsLineOutExit PUSH AX CALL MsCharOut ;Cntl-C Interrupt Check Disabled INC BX JMP SHORT MsLineOutLoop MsLineOutExit: POP BP RET 4 MsLineOut ENDP PURGE pLineOut ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsLineIn: PROCEDURE (pLineIn) CLEAN; ; DCL pLineIn PTR; pLineIn EQU DWORD PTR [BP+6] ; parm 1 MsLineIn PROC NEAR PUSH DS PUSH BP MOV BP, SP LDS DX, pLineIn MOV AH, 0AH CALL MsDos POP BP POP DS RET 4 MsLineIn ENDP PURGE pLineIn ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsPrintChar: PROCEDURE (char) CLEAN; ; DCL char BYTE; char EQU BYTE PTR [BP+4] ; parm 1 MsPrintChar PROC NEAR PUSH BP MOV BP, SP MOV DL, char MOV AH, 05H CALL MsDos POP BP RET 2 MsPrintChar ENDP PURGE char ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsPrintLine: PROCEDURE (pLineOut) CLEAN; ; DCL pLine PTR; pLineOut EQU DWORD PTR [BP+4] ; parm 1 MsPrintLine PROC NEAR PUSH BP MOV BP, SP LES BX, pLineOut MsPrintLineLoop: MOV DL, ES:[BX] CMP DL, '$' JE MsPrintLineExit MOV AH, 05H CALL MsDos INC BX JMP SHORT MsPrintLineLoop MsPrintLineExit: POP BP RET 4 MsPrintLine ENDP PURGE pLineOut ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsAttach: PROCEDURE (pPathName, mode, access, attribute, pError) WORD CLEAN; ; DCL mode BYTE; ; DCL access BYTE; ; DCL attribute WORD; ; DCL pPathname PTR; ; DCL pError PTR; pError EQU DWORD PTR [BP+6] ; parm 5 attribute EQU WORD PTR [BP+10] ; parm 4 access EQU BYTE PTR [BP+12] ; parm 3 mode EQU BYTE PTR [BP+14] ; parm 2 pPathname EQU DWORD PTR [BP+16] ; parm 1 MsAttach PROC NEAR PUSH DS PUSH BP MOV BP, SP MOV AL, mode DEC AL CMP AL, newFile JG MsAttachInvalidMode LDS DX, pPathname ; DS:DX => pathname CMP AL, oldFile JE MsAttachIsOpen MsAttachIsCreate: MOV CX, attribute MOV AH, 3CH CALL MsDos ; create JMP SHORT MsAttachCheckError MsAttachIsOpen: MOV AL, access MOV AH, 3DH CALL MsDos ; open JMP SHORT MsAttachCheckError MsAttachInvalidMode: MOV AX, eMsInvalidParm STC MsAttachCheckError: LDS DI, pError MOV WORD PTR DS:[DI], eOK JNC MsAttachExit MOV DS:[DI], AX ; DS:DI => Error MsAttachExit: POP BP ; AX = conn POP DS RET 14 MsAttach ENDP PURGE pError, attribute, access, mode, pPathname ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsRead: PROCEDURE (conn, pBuffer, count, pError) WORD CLEAN; ; DCL conn WORD; ; DCL count WORD; ; DCL pBuffer PTR; ; DCL pError PTR; pError EQU DWORD PTR [BP+6] ; parm 4 count EQU WORD PTR [BP+10] ; parm 3 pBuffer EQU DWORD PTR [BP+12] ; parm 2 conn EQU WORD PTR [BP+16] ; parm 1 MsRead PROC NEAR PUSH DS PUSH BP MOV BP, SP MOV BX, conn MOV CX, count LDS DX, pBuffer MOV AH, 3FH CALL MsDos LDS DI, pError MOV WORD PTR DS:[DI], eOK JNC MsReadExit MOV DS:[DI], AX ; DS:DI => Error MsReadExit: POP BP ; AX = # bytes read POP DS RET 12 MsRead ENDP PURGE pError, count, pBuffer, conn ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsWrite: PROCEDURE (conn, pBuffer, count, pError) WORD CLEAN; ; DCL conn WORD; ; DCL count WORD; ; DCL pBuffer PTR; ; DCL pError PTR; pError EQU DWORD PTR [BP+6] ; parm 4 count EQU WORD PTR [BP+10] ; parm 3 pBuffer EQU DWORD PTR [BP+12] ; parm 2 conn EQU WORD PTR [BP+16] ; parm 1 MsWrite PROC NEAR PUSH DS PUSH BP MOV BP, SP MOV BX, conn MOV CX, count LDS DX, pBuffer MOV AH, 40H CALL MsDos LDS DI, pError MOV WORD PTR DS:[DI], eOK JNC MsWriteExit MOV DS:[DI], AX ; DS:DI => Error MsWriteExit: POP BP ; AX = # bytes written POP DS RET 12 MsWrite ENDP PURGE pError, count, pBuffer, conn ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsSeek: PROCEDURE (conn, mode, count, pError) DWORD CLEAN; ; DCL mode BYTE; ; DCL conn WORD; ; DCL count DWORD; ; DCL pError PTR; seekBegPlus EQU 0 seekCurPlus EQU 1 seekEndPlus EQU 2 pError EQU DWORD PTR [BP+6] ; parm 4 count EQU DWORD PTR [BP+10] ; parm 3 mode EQU BYTE PTR [BP+14] ; parm 2 conn EQU WORD PTR [BP+16] ; parm 1 MsSeek PROC NEAR PUSH DS PUSH BP MOV BP, SP LDS DX, count MOV CX, DS ; CX:DX => count MOV BX, conn ; BX = conn MOV AL, mode ; AL = mode MOV AH, 42H CALL MsDos LDS DI, pError MOV WORD PTR DS:[DI], eOK JNC MsSeekExit MOV DS:[DI], AX ; DS:DI => Error MsSeekExit: POP BP ; DX:AX => new file position POP DS RET 12 MsSeek ENDP PURGE pError, count, mode, conn ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsRename: PROCEDURE (pOldName, pNewName, pError) CLEAN; ; DCL pOldName PTR; ; DCL pNewName PTR; ; DCL pError PTR; pError EQU DWORD PTR [BP+6] ; parm 3 pNewName EQU DWORD PTR [BP+10] ; parm 2 pOldName EQU DWORD PTR [BP+14] ; parm 1 MsRename PROC NEAR PUSH DS PUSH BP MOV BP, SP LDS DX, pOldName LES DI, pNewName MOV AH, 56H CALL MsDos LDS DI, pError MOV WORD PTR DS:[DI], eOK JNC MsRenameExit MOV DS:[DI], AX ; DS:DI => Error MsRenameExit: POP BP POP DS RET 12 MsRename ENDP PURGE pError, pNewName, pOldName ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsDelete: PROCEDURE (pPathname, pError) CLEAN; ; DCL pPathname PTR; ; DCL pError PTR; pError EQU DWORD PTR [BP+6] ; parm 2 pPathName EQU DWORD PTR [BP+10] ; parm 1 MsDelete PROC NEAR PUSH DS PUSH BP MOV BP, SP LDS DX, pPathname MOV AH, 41H CALL MsDos LDS DI, pError MOV WORD PTR DS:[DI], eOK JNC MsDeleteExit MOV DS:[DI], AX ; DS:DI => Error MsDeleteExit: POP BP POP DS RET 8 MsDelete ENDP PURGE pError, pPathname ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsAddDirectory: PROCEDURE (pDirName, pError) CLEAN; ; DCL pDirName PTR; ; DCL pError PTR; pError EQU DWORD PTR [BP+6] ; parm 2 pDirName EQU DWORD PTR [BP+10] ; parm 1 MsAddDirectory PROC NEAR PUSH DS PUSH BP MOV BP, SP LDS DX, pDirName MOV AH, 39H CALL MsDos LDS DI, pError MOV WORD PTR DS:[DI], eOK JNC MsAddDirectoryExit MOV DS:[DI], AX ; DS:DI => Error MsAddDirectoryExit: POP BP POP DS RET 8 MsAddDirectory ENDP PURGE pError, pDirName ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsDeleteDirectory: PROCEDURE (pDirName, pError) CLEAN; ; DCL pDirName PTR; ; DCL pError PTR; pError EQU DWORD PTR [BP+6] ; parm 2 pDirName EQU DWORD PTR [BP+10] ; parm 1 MsDeleteDirectory PROC NEAR PUSH DS PUSH BP MOV BP, SP LDS DX, pDirName MOV AH, 3AH CALL MsDos LDS DI, pError MOV WORD PTR DS:[DI], eOK JNC MsDeleteDirectoryExit MOV DS:[DI], AX ; DS:DI => Error MsDeleteDirectoryExit: POP BP POP DS RET 8 MsDeleteDirectory ENDP PURGE pError, pDirName ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsSetCurrentDirectory: PROCEDURE (pDirName, pError) CLEAN; ; DCL pDirName PTR; ; DCL pError PTR; pError EQU DWORD PTR [BP+6] ; parm 2 pDirName EQU DWORD PTR [BP+10] ; parm 1 MsSetCurrentDirectory PROC NEAR PUSH DS PUSH BP MOV BP, SP LDS DX, pDirName MOV AH, 3BH CALL MsDos LDS DI, pError MOV WORD PTR DS:[DI], eOK JNC MsSetCurrentDirectoryExit MOV DS:[DI], AX ; DS:DI => Error MsSetCurrentDirectoryExit: POP BP POP DS RET 8 MsSetCurrentDirectory ENDP PURGE pError, pDirName ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsGetCurrentDirectory: PROCEDURE (drive, pDirName, pError) CLEAN; ; DCL drive BYTE; ; DCL pDirName PTR; ; DCL pError PTR; pError EQU DWORD PTR [BP+6] ; parm 3 pDirName EQU DWORD PTR [BP+10] ; parm 2 drive EQU BYTE PTR [BP+14] ; parm 1 MsGetCurrentDirectory PROC NEAR PUSH DS PUSH BP MOV BP, SP MOV DL, drive LDS DX, pDirName MOV AH, 47H CALL MsDos LDS DI, pError MOV WORD PTR DS:[DI], eOK JNC MsGetCurrentDirectoryExit MOV DS:[DI], AX ; DS:DI => Error MsGetCurrentDirectoryExit: POP BP POP DS RET 10 MsGetCurrentDirectory ENDP PURGE pError, pDirName, drive ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsFindFirstDirEntry: PROCEDURE (pPathname, attr, pError) CLEAN; ; DCL attr WORD; ; DCL pPathName PTR; ; DCL pError PTR; pError EQU DWORD PTR [BP+6] ; parm 3 attr EQU WORD PTR [BP+10] ; parm 2 pPathName EQU DWORD PTR [BP+12] ; parm 1 MsFindFirstDirEntry PROC NEAR PUSH DS PUSH BP MOV BP, SP MOV CX, attr LDS DX, pPathName MOV AH, 4EH CALL MsDos LDS DI, pError MOV WORD PTR DS:[DI], eOK JNC MsFindFirstDirEntryExit MOV DS:[DI], AX ; DS:DI => Error MsFindFirstDirEntryExit: POP BP POP DS RET 10 MsFindFirstDirEntry ENDP PURGE pError, attr, pPathname ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsFindNextDirEntry: PROCEDURE (pError) CLEAN; ; DCL pError PTR; pError EQU DWORD PTR [BP+6] ; parm 1 MsFindNextDirEntry PROC NEAR PUSH DS PUSH BP MOV BP, SP MOV AH, 4FH CALL MsDos LDS DI, pError MOV WORD PTR DS:[DI], eOK JNC MsFindNextDirEntryExit MOV DS:[DI], AX ; DS:DI => Error MsFindNextDirEntryExit: POP BP POP DS RET 4 MsFindNextDirEntry ENDP PURGE pError ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsChangeAttributes: PROCEDURE (pPathname, attr, mode, pError) WORD CLEAN; ; DCL mode BYTE; ; DCL attr WORD; ; DCL pPathname PTR; ; DCL pError PTR; pError EQU DWORD PTR [BP+6] ; parm 4 mode EQU BYTE PTR [BP+10] ; parm 3 attr EQU WORD PTR [BP+12] ; parm 2 pPathname EQU DWORD PTR [BP+14] ; parm 1 MsChangeAttributes PROC NEAR PUSH DS PUSH BP MOV BP, SP MOV AL, mode MOV CX, attr LDS DX, pPathname MOV AH, 43H CALL MsDos LDS DI, pError MOV WORD PTR DS:[DI], eOK JNC MsChangeAttributesExit MOV DS:[DI], AX ; DS:DI => Error MsChangeAttributesExit: MOV AX, CX ; attributes POP BP POP DS RET 12 MsChangeAttributes ENDP PURGE pError, mode, attr, pPathname ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsIOControl: PROCEDURE (conn, pBuffer, count, mode, pError) WORD CLEAN; ; DCL mode BYTE; ; DCL conn WORD; ; DCL count WORD; ; DCL pBuffer PTR; ; DCL pError PTR; pError EQU DWORD PTR [BP+6] ; parm 5 mode EQU BYTE PTR [BP+10] ; parm 4 count EQU WORD PTR [BP+12] ; parm 3 pBuffer EQU DWORD PTR [BP+14] ; parm 2 conn EQU WORD PTR [BP+18] ; parm 1 MsIOControl PROC NEAR PUSH DS PUSH BP MOV BP, SP MOV AL, mode MOV BX, conn MOV CX, count LDS DX, pBuffer MOV AH, 44H CALL MsDos LDS DI, pError MOV WORD PTR DS:[DI], eOK JNC MsIOControlExit MOV DS:[DI], AX ; DS:DI => Error MsIOControlExit: POP BP ; AX = Return info POP DS RET 14 MsIOControl ENDP PURGE pError, mode, count, pBuffer, conn ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsFCBAttach: PROCEDURE (pFCB, mode, pStatus) WORD CLEAN; ; DCL mode BYTE; ; DCL pFCB PTR; ; DCL pStatus PTR; pStatus EQU DWORD PTR [BP+6] ; parm 3 mode EQU BYTE PTR [BP+10] ; parm 2 pFCB EQU DWORD PTR [BP+12] ; parm 1 MsFCBAttach PROC NEAR PUSH DS PUSH BP MOV BP, SP LDS DX, pFCB MOV AL, mode CMP AL, newFile JE MsFCBAttachCreate MsFCBAttachOpen: MOV AH, 0FH CALL MsDos JMP SHORT MsFCBAttachExit MsFCBAttachCreate: MOV AH, 16H CALL MsDos MsFCBAttachExit: LDS DI, pStatus MOV DS:[DI], AL POP BP POP DS RET 10 MsFCBAttach ENDP PURGE pStatus, mode, pFCB ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsFCBDetach: PROCEDURE (pFCB, pStatus) CLEAN; ; DCL pFCB PTR; ; DCL pStatus PTR; pStatus EQU DWORD PTR [BP+6] ; parm 2 pFCB EQU DWORD PTR [BP+10] ; parm 1 MsFCBDetach PROC NEAR PUSH DS PUSH BP MOV BP, SP LDS DX, pFCB MOV AH, 10H CALL MsDos LDS DI, pStatus MOV DS:[DI], AL POP BP POP DS RET 8 MsFCBDetach ENDP PURGE pStatus, pFCB ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsFCBRead: PROCEDURE (pFCB, mode, count, pStatus) WORD CLEAN; ; DCL mode BYTE; ; DCL count WORD; ; DCL pFCB PTR; ; DCL pStatus PTR; pStatus EQU DWORD PTR [BP+6] ; parm 4 count EQU WORD PTR [BP+10] ; parm 3 mode EQU BYTE PTR [BP+12] ; parm 2 pFCB EQU DWORD PTR [BP+14] ; parm 1 MsFCBRead PROC NEAR PUSH DS PUSH BP MOV BP, SP MOV CX, count LDS DX, pFCB MOV AL, mode OR AL, AL JNZ MsFCBRndRead MsFCBSeqRead: MOV AH, 14H ; mode = 0 = seq CALL MsDos JMP SHORT MsFCBReadExit MsFCBRndRead: DEC AL JNZ MsFCBRndBlkRead MOV AH, 21H ; mode = 1 = rnd CALL MsDos JMP SHORT MsFCBReadExit MsFCBRndBlkRead: DEC AL MOV AL, 0FFH JNZ MsFCBReadExit MOV AH, 27H ; mode = 2 = rnd blk CALL MsDos MsFCBReadExit: LDS DI, pStatus MOV DS:[DI], AL POP BP POP DS RET 12 MsFCBRead ENDP PURGE pStatus, count, mode, pFCB ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsFCBWrite: PROCEDURE (pFCB, mode, count, pStatus) WORD CLEAN; ; DCL mode BYTE; ; DCL count WORD; ; DCL pFCB PTR; ; DCL pStatus PTR; pStatus EQU DWORD PTR [BP+6] ; parm 4 count EQU WORD PTR [BP+10] ; parm 3 mode EQU BYTE PTR [BP+12] ; parm 2 pFCB EQU DWORD PTR [BP+14] ; parm 1 MsFCBWrite PROC NEAR PUSH DS PUSH BP MOV BP, SP MOV CX, count LDS DX, pFCB MOV AL, mode OR AL, AL JNZ MsFCBRndWrite MsFCBSeqWrite: MOV AH, 15H ; mode = 0 = seq CALL MsDos JMP SHORT MsFCBWriteExit MsFCBRndWrite: DEC AL JNZ MsFCBRndBlkWrite MOV AH, 22H ; mode = 1 = rnd CALL MsDos JMP SHORT MsFCBWriteExit MsFCBRndBlkWrite: DEC AL MOV AL, 0FFH JNZ MsFCBWriteExit MOV AH, 28H ; mode = 2 = rnd blk CALL MsDos MsFCBWriteExit: LDS DI, pStatus MOV DS:[DI], AL MOV AX, CX POP BP POP DS RET 12 MsFCBWrite ENDP PURGE pStatus, count, mode, pFCB ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsFCBRename: PROCEDURE (pFCB, pStatus) CLEAN; ; DCL pFCB PTR; ; DCL pStatus PTR; pStatus EQU DWORD PTR [BP+6] ; parm 2 pFCB EQU DWORD PTR [BP+10] ; parm 1 MsFCBRename PROC NEAR PUSH DS PUSH BP MOV BP, SP LDS DX, pFCB MOV AH, 17H CALL MsDos LDS DI, pStatus MOV DS:[DI], AL POP BP POP DS RET 8 MsFCBRename ENDP PURGE pStatus, pFCB ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsFCBDelete: PROCEDURE (pFCB, pStatus) CLEAN; ; DCL pFCB PTR; ; DCL pStatus PTR; pStatus EQU DWORD PTR [BP+6] ; parm 2 pFCB EQU DWORD PTR [BP+10] ; parm 1 MsFCBDelete PROC NEAR PUSH DS PUSH BP MOV BP, SP LDS DX, pFCB MOV AH, 13H CALL MsDos LDS DI, pStatus MOV DS:[DI], AL POP BP POP DS RET 8 MsFCBDelete ENDP PURGE pStatus, pFCB ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsFCBFirstEntry: PROCEDURE (pFCB, pStatus) CLEAN; ; DCL pFCB PTR; ; DCL pStatus PTR; pStatus EQU DWORD PTR [BP+6] ; parm 2 pFCB EQU DWORD PTR [BP+10] ; parm 1 MsFCBFirstEntry PROC NEAR PUSH DS PUSH BP MOV BP, SP LDS DX, pFCB MOV AH, 11H CALL MsDos LDS DI, pStatus MOV DS:[DI], AL POP BP POP DS RET 8 MsFCBFirstEntry ENDP PURGE pStatus, pFCB ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsFCBNextEntry: PROCEDURE (pFCB, pStatus) CLEAN; ; DCL pFCB PTR; ; DCL pStatus PTR; pStatus EQU DWORD PTR [BP+6] ; parm 2 pFCB EQU DWORD PTR [BP+10] ; parm 1 MsFCBNextEntry PROC NEAR PUSH DS PUSH BP MOV BP, SP LDS DX, pFCB MOV AH, 12H CALL MsDos LDS DI, pStatus MOV DS:[DI], AL POP BP POP DS RET 8 MsFCBNextEntry ENDP PURGE pStatus, pFCB ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsFCBFileSize: PROCEDURE (pFCB, pStatus) CLEAN; ; DCL pFCB PTR; ; DCL pStatus PTR; pStatus EQU DWORD PTR [BP+6] ; parm 2 pFCB EQU DWORD PTR [BP+10] ; parm 1 MsFCBFileSize PROC NEAR PUSH DS PUSH BP MOV BP, SP LDS DX, pFCB MOV AH, 23H CALL MsDos LDS DI, pStatus MOV DS:[DI], AL POP BP POP DS RET 8 MsFCBFileSize ENDP PURGE pStatus, pFCB ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsFCBSetRelativeRecord: PROCEDURE (pFCB) CLEAN; ; DCL pFCB PTR; pFCB EQU DWORD PTR [BP+6] ; parm 1 MsFCBSetRelativeRecord PROC NEAR PUSH DS PUSH BP MOV BP, SP LDS DX, pFCB MOV AH, 24H CALL MsDos POP BP POP DS RET 4 MsFCBSetRelativeRecord ENDP PURGE pFCB ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsFCBParseFileName: PROCEDURE (controls, pString, pFCB, pStatus) PTR CLEAN; ; DCL controls BYTE; ; DCL pString PTR; ; DCL pFCB PTR; ; DCL pStatus PTR; pStatus EQU DWORD PTR [BP+6] ; parm 4 pFCB EQU DWORD PTR [BP+10] ; parm 3 pString EQU DWORD PTR [BP+14] ; parm 2 controls EQU BYTE PTR [BP+18] ; parm 1 MsFCBParseFileName PROC NEAR PUSH DS PUSH BP MOV BP, SP LES DI, pFCB LDS SI, pString MOV AL, controls MOV AH, 29H CALL MsDos PUSH DS ; DS:SI => next part of string POP ES MOV BX, SI ; Return it in ES:BX LDS DI, pStatus MOV DS:[DI], AL ; AL = error POP BP POP DS RET 14 MsFCBParseFileName ENDP PURGE pStatus, pFCB, pString, controls ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsFlushAllDisks: PROCEDURE CLEAN; MsFlushAllDisks PROC NEAR MOV AH, 0DH CALL MsDos RET MsFlushAllDisks ENDP ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsSetDiskXferAddr: PROCEDURE (pAddr) CLEAN; ; DCL pAddr PTR; pAddr EQU DWORD PTR [BP+6] ; parm 1 MsSetDiskXferAddr PROC NEAR PUSH DS PUSH BP MOV BP, SP LDS DX, pAddr MOV AH, 1AH CALL MsDos POP BP POP DS RET 4 MsSetDiskXferAddr ENDP PURGE pAddr ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsGetDiskFreeSpace: PROCEDURE (drive, pInfo) CLEAN; ; DCL drive BYTE; ; DCL pInfo PTR; pInfo EQU DWORD PTR [BP+6] ; parm 2 drive EQU BYTE PTR [BP+10] ; parm 1 MsGetDiskFreeSpace PROC NEAR PUSH DS PUSH BP MOV BP, SP MOV DL, drive MOV AH, 36H CALL MsDos LDS DI, pInfo MOV [DI+0], BX MOV [DI+2], DX MOV [DI+4], CX MOV [DI+6], AX POP BP POP DS RET 6 MsGetDiskFreeSpace ENDP PURGE pInfo, drive ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsAllocate: PROCEDURE (numBlks, pError) PTR CLEAN; ; DCL numBlks WORD; ; DCL pError PTR; pError EQU DWORD PTR [BP+6] ; parm 2 numBlks EQU WORD PTR [BP+10] ; parm 1 MsAllocate PROC NEAR PUSH DS PUSH BP MOV BP, SP MOV BX, numBlks MOV AH, 48H CALL MsDos LDS DI, pError MOV WORD PTR DS:[DI], eOK JNC MsAllocateExit MOV DS:[DI], AX ; DS:DI => Error MsAllocateExit: MOV ES, AX XOR BX, BX ; ES:BX => Memory POP BP POP DS RET 6 MsAllocate ENDP PURGE pError, numBlks ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsFree: PROCEDURE (pBlock, pError) CLEAN; ; DCL pBlock PTR; ; DCL pError PTR; pError EQU DWORD PTR [BP+6] ; parm 2 pBlock EQU DWORD PTR [BP+10] ; parm 1 MsFree PROC NEAR PUSH DS PUSH BP MOV BP, SP LES SI, pBlock MOV AH, 49H CALL MsDos LDS DI, pError MOV WORD PTR DS:[DI], eOK JNC MsFreeExit MOV DS:[DI], AX ; DS:DI => Error MsFreeExit: POP BP POP DS RET 8 MsFree ENDP PURGE pError, pBlock ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsAvailableMemory: PROCEDURE WORD CLEAN; MsAvailableMemory PROC NEAR MOV BX, 0FFFFH MOV AH, 48H ; Allocate CALL MsDos MOV AX, BX RET MsAvailableMemory ENDP ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsInMsDosPtr: PROCEDURE PTR CLEAN; MsInMsDosPtr PROC NEAR MOV AH, 34H CALL MsDos RET MsInMsDosPtr ENDP ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsGetEntrypoint: PROCEDURE (pSignature, pError) PTR CLEAN; ; DCL pDeviceHeader PTR; ; DCL pRequestBlock PTR; pError EQU DWORD PTR [BP+6] ; parm 2 pSignature EQU DWORD PTR [BP+10] ; parm 1 MsGetEntrypoint PROC NEAR PUSH DS PUSH BP MOV BP, SP LES BX, pSignature LDS DI, pError PUSH DS PUSH DI ; save @error MOV CX, BX ; pSignature is MOV BX, ES ; passed in BX:CX XOR AX, AX MOV DX, AX ; Registers MOV DI, AX ; DX, DI, SI, BP MOV SI, AX ; must be zero MOV BP, AX DEC AX MOV DS, AX ; DS & ES must be MOV ES, AX ; NULLWORD MOV AX, 0C98H ; Use flush kbd CALL MsDos ; fnc w/ 98H INC AX ; Upon return JNZ MsGetEntryErrorExit ; AX = NULLWORD MOV AX, DS ; And DS must OR AX, AX ; be zero JNZ MsGetEntryErrorExit INC DX INC DI INC SI INC BP MOV AX, ES ; And ES must OR AX, DX ; be zero; plus OR AX, DI ; registers DX, OR AX, SI ; DI, SI and BP OR AX, BP ; must be NULLWORD JNZ MsGetEntryErrorExit ; for valid return MOV ES, BX ; @ entrypoint is MOV BX, CX ; in BX:CX JMP SHORT MsGetEntrypointExit MsGetEntryErrorExit: MOV AX, 0FFFFH MOV ES, AX MOV BX, 0FH ; RETURN (NULLPTR) MsGetEntrypointExit: POP DI POP DS ; @error MOV DS:[DI], AX POP BP POP DS RET 8 MsGetEntrypoint ENDP PURGE pError, pSignature ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsSetCntlCInterrupt: PROCEDURE (cntlCRtnOffset) CLEAN; ; Cntl-C Interrupt number is 23H cntlCRtnOffset EQU WORD PTR [BP+4] MsSetCntlCInterrupt PROC NEAR PUSH BP MOV BP, SP MOV AX, 3301H ; Set Cntl-C Check State MOV DL, 0 ; To off CALL MsDos MOV AX, cntlCRtnOffset MOV cntlCHandlerAddr, AX PUSH DS PUSH CS POP DS MOV DX, OFFSET CntlCHandler MOV AX, 2523H CALL MsDos POP DS POP BP RET 2 MsSetCntlCInterrupt ENDP ) FI $EJECT %IF (%systemType EQ 2) THEN ( userStackSS DW ? userStackSP DW ? CntlCHandler PROC FAR MOV CS:userStackSS, SS MOV CS:userStackSP, SP MOV SP, SEG DGROUP:cntlCStackTop MOV SS, SP MOV SP, OFFSET DGROUP:cntlCStackTop PUSH AX PUSH BX PUSH CX PUSH DX PUSH SI PUSH DI PUSH BP PUSH DS PUSH ES PUSH SS POP DS MOV DI, cntlCHandlerAddr CALL DI POP ES POP DS POP BP POP DI POP SI POP DX POP CX POP BX POP AX MOV SS, CS:userStackSS MOV SP, CS:userStackSP IRET CntlCHandler ENDP ) FI $EJECT ; Video Routines: PROCEDURE CLEAN; VideoRtns PROC NEAR PUSH BP INT 10H ; PC Video Interrupt POP BP RET VideoRtns ENDP ; MsGetMachineType: PROCEDURE BYTE CLEAN; MsGetMachineType PROC NEAR MOV AL, machineType CMP AL, noMachine JNE MsGetMachineTypeExit MOV AX, 0FFFH ; Current Video State CALL VideoRtns ; PC Video Interrupt INC AL ; If AL still = 0FF JZ MsGetMachineTypeSetIt ; Type of 0 => Compass MOV AL, pcMachine ; Type of 1 => PC MsGetMachineTypeSetIt: MOV machineType, AL MsGetMachineTypeExit: RET MsGetMachineType ENDP $EJECT %IF (%systemType EQ 2) THEN ( ; MsTurnCursorOn: PROCEDURE CLEAN; MsTurnCursorOn PROC NEAR PUSH BP MOV BP, SP TEST cursorOn, TRUE ; If cursor is already on JNZ MsTurnCursorOnExit ; then do nothing MOV cursorOn, TRUE ; Set cursor state to on CALL MsGetMachineType OR AL, AL ; If type = 0 JZ MsTurnCpCursorOn ; then compass DEC AL ; Else if not = 1 JNZ MsTurnCursorOnExit ; then do nothing MsTurnPcCursorOn: MOV AH, 15 ; Get curr state CALL VideoRtns ; Video interrupt MOV CX, cursorType ; Get old cursor AND CH, 0DFH ; Turn on cursor CMP CL, 67H ; If NOT ROM bug version JNE SetCursorOn ; then use saved mode MOV CX, 0607H ; Default graphics display cursor mode CMP AL, 7 ; If not on monochrome display JNE SetCursorOn ; then use graphics values MOV CX, 0B0CH ; else use monochrome default cursor mode SetCursorOn: MOV AH, 1 ; Set cursor type CALL VideoRtns ; Video Interrupt JMP SHORT MsTurnCursorOnExit ; Exit MsTurnCpCursorOn: MOV AX, OFFSET cursorOnStr ; Send ANSI PUSH CS ; escape sequence PUSH AX ; to turn cursor CALL MsLineOut ; on MsTurnCursorOnExit: POP BP RET MsTurnCursorOn ENDP cursorOnStr DB 1BH, '[3;3z$' ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsTurnCursorOff: PROCEDURE CLEAN; MsTurnCursorOff PROC NEAR PUSH BP MOV BP, SP TEST cursorOn, TRUE ; If the cursor is already JZ MsTurnCursorOffExit ; off then do nothing MOV cursorOn, FALSE ; Set cursor state to off CALL MsGetMachineType OR AL, AL ; If type = 0 JZ MsTurnCpCursorOff ; then compass DEC AL ; Else if not = 1 JNZ MsTurnCursorOffExit ; then do nothing MsTurnPcCursorOff: MOV AH, 15 ; Get curr state CALL VideoRtns ; Video interrupt MOV AH, 3 ; Get cursor type CALL VideoRtns ; Video interrupt MOV cursorType, CX ; Save old cursor OR CH, 20H ; Turn off cursor MOV AH, 1 ; Set cursor type CALL VideoRtns ; Video interrupt JMP SHORT MsTurnCursorOffExit MsTurnCpCursorOff: MOV AX, OFFSET cursorOffStr ; Send ANSI esc PUSH CS ; sequence to PUSH AX ; turn cursor CALL MsLineOut ; off MsTurnCursorOffExit: POP BP RET MsTurnCursorOff ENDP cursorOffStr DB 1BH, '[3;4z$' ) FI $EJECT %IF (%systemType EQ 2) THEN ( ; MsGetPDB: PROCEDURE SELECTOR CLEAN; MsGetPDB PROC NEAR MOV AH, 51H CALL MsDos MOV AX, BX RET MsGetPDB ENDP ; MsSetPDB: PROCEDURE (sPDB) CLEAN; sPDB EQU WORD PTR [BP+4] MsSetPDB PROC NEAR PUSH BP MOV BP, SP MOV BX, sPDB MOV AH, 50H CALL MsDos POP BP RET 2 MsSetPDB ENDP PURGE sPDB ; MsDuplicatePDB: PROCEDURE (sPDB, hiMem) CLEAN; sPDB EQU WORD PTR [BP+6] hiMem EQU WORD PTR [BP+4] MsDuplicatePDB PROC NEAR PUSH BP MOV BP, SP MOV DX, sPDB MOV SI, hiMem MOV AH, 55H CALL MsDos POP BP RET 4 MsDuplicatePDB ENDP PURGE sPDB, hiMem ) FI $EJECT $LIST NOP $NOLIST CODE ENDS END