From 2d04cacc5322951f187bb17e017c12920ac8ebe2 Mon Sep 17 00:00:00 2001 From: Mark Zbikowski Date: Thu, 25 Apr 2024 21:24:10 +0100 Subject: MZ is back! --- v4.0/src/DOS/ABORT.ASM | 137 +++++ v4.0/src/DOS/ALLOC.ASM | 392 +++++++++++++ v4.0/src/DOS/BUF.ASM | 982 ++++++++++++++++++++++++++++++++ v4.0/src/DOS/CLOSE.ASM | 432 +++++++++++++++ v4.0/src/DOS/CPMIO.ASM | 448 +++++++++++++++ v4.0/src/DOS/CPMIO2.ASM | 354 ++++++++++++ v4.0/src/DOS/CREATE.ASM | 380 +++++++++++++ v4.0/src/DOS/CRIT.ASM | 92 +++ v4.0/src/DOS/CTRLC.ASM | 771 ++++++++++++++++++++++++++ v4.0/src/DOS/DELETE.ASM | 777 ++++++++++++++++++++++++++ v4.0/src/DOS/DEV.ASM | 841 ++++++++++++++++++++++++++++ v4.0/src/DOS/DINFO.ASM | 131 +++++ v4.0/src/DOS/DIR.ASM | 445 +++++++++++++++ v4.0/src/DOS/DIR2.ASM | 1353 +++++++++++++++++++++++++++++++++++++++++++++ v4.0/src/DOS/DIRCALL.ASM | 415 ++++++++++++++ v4.0/src/DOS/DISK.ASM | 1073 +++++++++++++++++++++++++++++++++++ v4.0/src/DOS/DISK2.ASM | 784 ++++++++++++++++++++++++++ v4.0/src/DOS/DISK3.ASM | 662 ++++++++++++++++++++++ v4.0/src/DOS/DISP.ASM | 579 +++++++++++++++++++ v4.0/src/DOS/DISPATCH.ASM | 214 +++++++ v4.0/src/DOS/DOSMES.ASM | 442 +++++++++++++++ v4.0/src/DOS/DOSPRINT.ASM | 36 ++ v4.0/src/DOS/DUP.ASM | 68 +++ v4.0/src/DOS/EXEC.ASM | 931 +++++++++++++++++++++++++++++++ v4.0/src/DOS/EXTATTR.ASM | 679 +++++++++++++++++++++++ v4.0/src/DOS/FAT.ASM | 695 +++++++++++++++++++++++ v4.0/src/DOS/FCB.ASM | 504 +++++++++++++++++ v4.0/src/DOS/FCBIO.ASM | 1185 +++++++++++++++++++++++++++++++++++++++ v4.0/src/DOS/FCBIO2.ASM | 722 ++++++++++++++++++++++++ v4.0/src/DOS/FILE.ASM | 909 ++++++++++++++++++++++++++++++ v4.0/src/DOS/FINFO.ASM | 286 ++++++++++ v4.0/src/DOS/GETSET.ASM | 912 ++++++++++++++++++++++++++++++ v4.0/src/DOS/HANDLE.ASM | 893 ++++++++++++++++++++++++++++++ v4.0/src/DOS/HIGHSW.ASM | 29 + v4.0/src/DOS/IFS.ASM | 523 ++++++++++++++++++ v4.0/src/DOS/IOCTL.ASM | 745 +++++++++++++++++++++++++ v4.0/src/DOS/ISEARCH.ASM | 364 ++++++++++++ v4.0/src/DOS/KSTRIN.ASM | 690 +++++++++++++++++++++++ v4.0/src/DOS/LOCK.ASM | 372 +++++++++++++ v4.0/src/DOS/MACRO.ASM | 445 +++++++++++++++ v4.0/src/DOS/MACRO2.ASM | 1281 ++++++++++++++++++++++++++++++++++++++++++ v4.0/src/DOS/MAKEFILE | 221 ++++++++ v4.0/src/DOS/MISC.ASM | 572 +++++++++++++++++++ v4.0/src/DOS/MISC2.ASM | 594 ++++++++++++++++++++ v4.0/src/DOS/MKNODE.ASM | 890 +++++++++++++++++++++++++++++ v4.0/src/DOS/MSCODE.ASM | 16 + v4.0/src/DOS/MSCONST.ASM | 153 +++++ v4.0/src/DOS/MSCPMIO.ASM | 17 + v4.0/src/DOS/MSCTRLC.ASM | 16 + v4.0/src/DOS/MSDISP.ASM | 17 + v4.0/src/DOS/MSDOS.LNK | 59 ++ v4.0/src/DOS/MSDOS.SKL | 17 + v4.0/src/DOS/MSHALO.ASM | 247 +++++++++ v4.0/src/DOS/MSINIT.ASM | 667 ++++++++++++++++++++++ v4.0/src/DOS/MSIOCTL.ASM | 5 + v4.0/src/DOS/MSPROC.ASM | 15 + v4.0/src/DOS/MSSW.ASM | 27 + v4.0/src/DOS/MS_CODE.ASM | 614 ++++++++++++++++++++ v4.0/src/DOS/MS_TABLE.ASM | 710 ++++++++++++++++++++++++ v4.0/src/DOS/NSTDOS.ASM | 7 + v4.0/src/DOS/OPEN.ASM | 569 +++++++++++++++++++ v4.0/src/DOS/PARSE.ASM | 447 +++++++++++++++ v4.0/src/DOS/PATH.ASM | 363 ++++++++++++ v4.0/src/DOS/PRINT.ASM | 199 +++++++ v4.0/src/DOS/PROC.ASM | 187 +++++++ v4.0/src/DOS/RENAME.ASM | 434 +++++++++++++++ v4.0/src/DOS/ROM.ASM | 938 +++++++++++++++++++++++++++++++ v4.0/src/DOS/SEARCH.ASM | 346 ++++++++++++ v4.0/src/DOS/SEGCHECK.ASM | 288 ++++++++++ v4.0/src/DOS/SHARE.ASM | 151 +++++ v4.0/src/DOS/SHRPRINT.ASM | 35 ++ v4.0/src/DOS/SRVCALL.ASM | 306 ++++++++++ v4.0/src/DOS/STDASW.ASM | 29 + v4.0/src/DOS/STDCODE.ASM | 17 + v4.0/src/DOS/STDCPMIO.ASM | 16 + v4.0/src/DOS/STDCTRLC.ASM | 15 + v4.0/src/DOS/STDDATA.ASM | 33 ++ v4.0/src/DOS/STDDISP.ASM | 16 + v4.0/src/DOS/STDDOSME.ASM | 20 + v4.0/src/DOS/STDIOCTL.ASM | 5 + v4.0/src/DOS/STDPROC.ASM | 15 + v4.0/src/DOS/STDSW.ASM | 32 ++ v4.0/src/DOS/STDTABLE.ASM | 16 + v4.0/src/DOS/STRIN.ASM | 403 ++++++++++++++ v4.0/src/DOS/TIME.ASM | 380 +++++++++++++ v4.0/src/DOS/UTIL.ASM | 232 ++++++++ 86 files changed, 34329 insertions(+) create mode 100644 v4.0/src/DOS/ABORT.ASM create mode 100644 v4.0/src/DOS/ALLOC.ASM create mode 100644 v4.0/src/DOS/BUF.ASM create mode 100644 v4.0/src/DOS/CLOSE.ASM create mode 100644 v4.0/src/DOS/CPMIO.ASM create mode 100644 v4.0/src/DOS/CPMIO2.ASM create mode 100644 v4.0/src/DOS/CREATE.ASM create mode 100644 v4.0/src/DOS/CRIT.ASM create mode 100644 v4.0/src/DOS/CTRLC.ASM create mode 100644 v4.0/src/DOS/DELETE.ASM create mode 100644 v4.0/src/DOS/DEV.ASM create mode 100644 v4.0/src/DOS/DINFO.ASM create mode 100644 v4.0/src/DOS/DIR.ASM create mode 100644 v4.0/src/DOS/DIR2.ASM create mode 100644 v4.0/src/DOS/DIRCALL.ASM create mode 100644 v4.0/src/DOS/DISK.ASM create mode 100644 v4.0/src/DOS/DISK2.ASM create mode 100644 v4.0/src/DOS/DISK3.ASM create mode 100644 v4.0/src/DOS/DISP.ASM create mode 100644 v4.0/src/DOS/DISPATCH.ASM create mode 100644 v4.0/src/DOS/DOSMES.ASM create mode 100644 v4.0/src/DOS/DOSPRINT.ASM create mode 100644 v4.0/src/DOS/DUP.ASM create mode 100644 v4.0/src/DOS/EXEC.ASM create mode 100644 v4.0/src/DOS/EXTATTR.ASM create mode 100644 v4.0/src/DOS/FAT.ASM create mode 100644 v4.0/src/DOS/FCB.ASM create mode 100644 v4.0/src/DOS/FCBIO.ASM create mode 100644 v4.0/src/DOS/FCBIO2.ASM create mode 100644 v4.0/src/DOS/FILE.ASM create mode 100644 v4.0/src/DOS/FINFO.ASM create mode 100644 v4.0/src/DOS/GETSET.ASM create mode 100644 v4.0/src/DOS/HANDLE.ASM create mode 100644 v4.0/src/DOS/HIGHSW.ASM create mode 100644 v4.0/src/DOS/IFS.ASM create mode 100644 v4.0/src/DOS/IOCTL.ASM create mode 100644 v4.0/src/DOS/ISEARCH.ASM create mode 100644 v4.0/src/DOS/KSTRIN.ASM create mode 100644 v4.0/src/DOS/LOCK.ASM create mode 100644 v4.0/src/DOS/MACRO.ASM create mode 100644 v4.0/src/DOS/MACRO2.ASM create mode 100644 v4.0/src/DOS/MAKEFILE create mode 100644 v4.0/src/DOS/MISC.ASM create mode 100644 v4.0/src/DOS/MISC2.ASM create mode 100644 v4.0/src/DOS/MKNODE.ASM create mode 100644 v4.0/src/DOS/MSCODE.ASM create mode 100644 v4.0/src/DOS/MSCONST.ASM create mode 100644 v4.0/src/DOS/MSCPMIO.ASM create mode 100644 v4.0/src/DOS/MSCTRLC.ASM create mode 100644 v4.0/src/DOS/MSDISP.ASM create mode 100644 v4.0/src/DOS/MSDOS.LNK create mode 100644 v4.0/src/DOS/MSDOS.SKL create mode 100644 v4.0/src/DOS/MSHALO.ASM create mode 100644 v4.0/src/DOS/MSINIT.ASM create mode 100644 v4.0/src/DOS/MSIOCTL.ASM create mode 100644 v4.0/src/DOS/MSPROC.ASM create mode 100644 v4.0/src/DOS/MSSW.ASM create mode 100644 v4.0/src/DOS/MS_CODE.ASM create mode 100644 v4.0/src/DOS/MS_TABLE.ASM create mode 100644 v4.0/src/DOS/NSTDOS.ASM create mode 100644 v4.0/src/DOS/OPEN.ASM create mode 100644 v4.0/src/DOS/PARSE.ASM create mode 100644 v4.0/src/DOS/PATH.ASM create mode 100644 v4.0/src/DOS/PRINT.ASM create mode 100644 v4.0/src/DOS/PROC.ASM create mode 100644 v4.0/src/DOS/RENAME.ASM create mode 100644 v4.0/src/DOS/ROM.ASM create mode 100644 v4.0/src/DOS/SEARCH.ASM create mode 100644 v4.0/src/DOS/SEGCHECK.ASM create mode 100644 v4.0/src/DOS/SHARE.ASM create mode 100644 v4.0/src/DOS/SHRPRINT.ASM create mode 100644 v4.0/src/DOS/SRVCALL.ASM create mode 100644 v4.0/src/DOS/STDASW.ASM create mode 100644 v4.0/src/DOS/STDCODE.ASM create mode 100644 v4.0/src/DOS/STDCPMIO.ASM create mode 100644 v4.0/src/DOS/STDCTRLC.ASM create mode 100644 v4.0/src/DOS/STDDATA.ASM create mode 100644 v4.0/src/DOS/STDDISP.ASM create mode 100644 v4.0/src/DOS/STDDOSME.ASM create mode 100644 v4.0/src/DOS/STDIOCTL.ASM create mode 100644 v4.0/src/DOS/STDPROC.ASM create mode 100644 v4.0/src/DOS/STDSW.ASM create mode 100644 v4.0/src/DOS/STDTABLE.ASM create mode 100644 v4.0/src/DOS/STRIN.ASM create mode 100644 v4.0/src/DOS/TIME.ASM create mode 100644 v4.0/src/DOS/UTIL.ASM (limited to 'v4.0/src/DOS') diff --git a/v4.0/src/DOS/ABORT.ASM b/v4.0/src/DOS/ABORT.ASM new file mode 100644 index 0000000..43268e3 --- /dev/null +++ b/v4.0/src/DOS/ABORT.ASM @@ -0,0 +1,137 @@ +; SCCSID = @(#)abort.asm 1.4 85/10/02 +TITLE DOS_ABORT - Internal SFT close all files for proc call for MSDOS +NAME DOS_ABORT + +; Internal Abort call closes all handles and FCBs associated with a process. +; If process has NET resources a close all is sent out over the net. +; +; DOS_ABORT +; +; Modification history: +; +; Created: ARR 30 March 1983 +; + +; +; get the appropriate segment definitions +; + +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xlist +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +.cref +.list + +Installed = TRUE + + I_Need PROC_ID,WORD ; current process ID + I_Need USER_ID,WORD ; current user ID + i_need CurrentPDB,WORD + i_need sft_addr,DWORD + i_need THISSFT,DWORD + i_need JSHARE,DWORD + I_need sftFCB,DWORD ; pointer to SFTs for FCB cache + +Break + +; Inputs: +; [CurrentPDB] set to PID of process aborting +; Function: +; Close all files and free all SFTs for this PID +; Returns: +; None +; All destroyed except stack + + Procedure DOS_ABORT,NEAR + ASSUME DS:NOTHING,ES:NOTHING + + MOV ES,[CurrentPDB] + MOV CX,ES:[PDB_JFN_Length] ; Number of JFNs +reset_free_jfn: + MOV BX,CX + PUSH CX + DEC BX ; get jfn (start with last one) + + invoke $close + POP CX + LOOP reset_free_jfn ; and do 'em all +; +; Note: We do need to explicitly close FCBs. Reasons are as follows: If we +; are running in the no-sharing no-network environment, we are simulating the +; 2.0 world and thus if the user doesn't close the file, that is his problem +; BUT... the cache remains in a state with garbage that may be reused by the +; next process. We scan the set and blast the ref counts of the FCBs we own. +; +; If sharing is loaded, then the following call to close process will +; correctly close all FCBs. We will then need to walk the list AFTER here. +; +; Finally, the following call to NET_Abort will cause an EOP to be sent to all +; known network resources. These resources are then responsible for cleaning +; up after this process. +; +; Sleazy, eh? +; + context DS + CallInstall Net_Abort, multNet, 29 +if installed + call JShare + 4 * 4 +else + call mftCloseP +endif + assume ds:nothing +; +; Scan the FCB cache for guys that belong to this process and zap their ref +; counts. +; + les di,sftFCB ; grab the pointer to the table + mov cx,es:[di].sfCount + jcxz FCBScanDone + LEA DI,[DI].sfTable ; point at table + mov ax,proc_id +FCBTest: + cmp es:[di].sf_PID,ax ; is this one of ours + jnz FCBNext ; no, skip it + mov es:[di].sf_ref_count,0 ; yes, blast ref count +FCBNext: + add di,size sf_Entry + loop FCBTest +FCBScanDone: + +; +; Walk the SFT to eliminate all busy SFT's for this process. +; + XOR BX,BX +Scan: + push bx + invoke SFFromSFN + pop bx + retc + cmp es:[di].sf_ref_count,0 + jz next +; +; we have a SFT that is not free. See if it is for the current process +; + mov ax,proc_id + cmp es:[di].sf_pid,ax + jnz next + mov ax,user_id + cmp es:[di].sf_uid,ax + jnz next +; +; This SFT is labelled as ours. +; + mov es:[di].sf_ref_count,0 +next: + inc bx + jmp scan + +EndProc DOS_Abort + +CODE ENDS + END diff --git a/v4.0/src/DOS/ALLOC.ASM b/v4.0/src/DOS/ALLOC.ASM new file mode 100644 index 0000000..37b6298 --- /dev/null +++ b/v4.0/src/DOS/ALLOC.ASM @@ -0,0 +1,392 @@ +; SCCSID = @(#)alloc.asm 1.1 85/04/09 +TITLE ALLOC.ASM - memory arena manager +NAME Alloc +; +; Memory related system calls and low level routines for MSDOS 2.X. +; I/O specs are defined in DISPATCH. +; +; $ALLOC +; $SETBLOCK +; $DEALLOC +; $AllocOper +; arena_free_process +; arena_next +; check_signature +; Coalesce +; +; Modification history: +; +; Created: ARR 30 March 1983 +; + +.xlist +; +; get the appropriate segment definitions +; +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +.cref +.list + +.lall + +SUBTTL memory allocation utility routines +PAGE +; +; arena data +; + i_need arena_head,WORD ; seg address of start of arena + i_need CurrentPDB,WORD ; current process data block addr + i_need FirstArena,WORD ; first free block found + i_need BestArena,WORD ; best free block found + i_need LastArena,WORD ; last free block found + i_need AllocMethod,BYTE ; how to alloc first(best)last + I_need EXTERR_LOCUS,BYTE ; Extended Error Locus + +; +; arena_free_process +; input: BX - PID of process +; output: free all blocks allocated to that PID +; + procedure arena_free_process,NEAR + ASSUME DS:NOTHING,ES:NOTHING + MOV DI,arena_signature + MOV AX,[arena_head] + CALL Check_Signature ; ES <- AX, check for valid block + +arena_free_process_loop: + retc + PUSH ES + POP DS + CMP DS:[arena_owner],BX ; is block owned by pid? + JNZ arena_free_next ; no, skip to next + MOV DS:[arena_owner],DI ; yes... free him + +arena_free_next: + CMP BYTE PTR DS:[DI],arena_signature_end + ; end of road, Jack? + retz ; never come back no more + CALL arena_next ; next item in ES/AX carry set if trash + JMP arena_free_process_loop + +EndProc arena_free_process + +; +; arena_next +; input: DS - pointer to block head +; output: AX,ES - pointers to next head +; carry set if trashed arena +; + procedure arena_next,NEAR + ASSUME DS:NOTHING,ES:NOTHING + MOV AX,DS ; AX <- current block + ADD AX,DS:[arena_size] ; AX <- AX + current block length + INC AX ; remember that header! +; +; fall into check_signature and return +; +; CALL check_signature ; ES <- AX, carry set if error +; RET +EndProc arena_next + +; +; check_signature +; input: AX - address of block header +; output: ES=AX, carry set if signature is bad +; + procedure check_signature,NEAR + ASSUME DS:NOTHING,ES:NOTHING + MOV ES,AX ; ES <- AX + CMP BYTE PTR ES:[DI],arena_signature_normal + ; IF next signature = not_end THEN + retz ; GOTO ok + CMP BYTE PTR ES:[DI],arena_signature_end + ; IF next signature = end then + retz ; GOTO ok + STC ; set error + return + +EndProc Check_signature + +; +; Coalesce - combine free blocks ahead with current block +; input: DS - pointer to head of free block +; output: updated head of block, AX is next block +; carry set -> trashed arena +; + procedure Coalesce,NEAR + ASSUME DS:NOTHING,ES:NOTHING + CMP BYTE PTR DS:[DI],arena_signature_end + ; IF current signature = END THEN + retz ; GOTO ok + CALL arena_next ; ES, AX <- next block, Carry set if error + retc ; IF no error THEN GOTO check + +coalesce_check: + CMP ES:[arena_owner],DI + retnz ; IF next block isnt free THEN return + MOV CX,ES:[arena_size] ; CX <- next block size + INC CX ; CX <- CX + 1 (for header size) + ADD DS:[arena_size],CX ; current size <- current size + CX + MOV CL,ES:[DI] ; move up signature + MOV DS:[DI],CL + JMP coalesce ; try again +EndProc Coalesce + +SUBTTL $Alloc - allocate space in memory +PAGE +; +; Assembler usage: +; MOV BX,size +; MOV AH,Alloc +; INT 21h +; AX:0 is pointer to allocated memory +; BX is max size if not enough memory +; +; Description: +; Alloc returns a pointer to a free block of +; memory that has the requested size in paragraphs. +; +; Error return: +; AX = error_not_enough_memory +; = error_arena_trashed +; + procedure $ALLOC,NEAR + ASSUME DS:NOTHING,ES:NOTHING + + EnterCrit critMem + XOR AX,AX + MOV DI,AX + + MOV [FirstArena],AX ; init the options + MOV [BestArena],AX + MOV [LastArena],AX + + PUSH AX ; alloc_max <- 0 + MOV AX,[arena_head] ; AX <- beginning of arena + CALL Check_signature ; ES <- AX, carry set if error + JC alloc_err ; IF error THEN GOTO err + +alloc_scan: + PUSH ES + POP DS ; DS <- ES + CMP DS:[arena_owner],DI + JZ alloc_free ; IF current block is free THEN examine + +alloc_next: + CMP BYTE PTR DS:[DI],arena_signature_end + ; IF current block is last THEN + JZ alloc_end ; GOTO end + CALL arena_next ; AX, ES <- next block, Carry set if error + JNC alloc_scan ; IF no error THEN GOTO scan + +alloc_err: + POP AX + +alloc_trashed: + LeaveCrit critMem + error error_arena_trashed + +alloc_end: + CMP [FirstArena],0 + JNZ alloc_do_split + +alloc_fail: + invoke get_user_stack + POP BX + MOV [SI].user_BX,BX + LeaveCrit critMem + error error_not_enough_memory + +alloc_free: + CALL coalesce ; add following free block to current + JC alloc_err ; IF error THEN GOTO err + MOV CX,DS:[arena_size] + + POP DX ; check for max found size + CMP CX,DX + JNA alloc_test + MOV DX,CX + +alloc_test: + PUSH DX + CMP BX,CX ; IF BX > size of current block THEN + JA alloc_next ; GOTO next + + CMP [FirstArena],0 + JNZ alloc_best + MOV [FirstArena],DS ; save first one found +alloc_best: + CMP [BestArena],0 + JZ alloc_make_best ; initial best + PUSH ES + MOV ES,[BestArena] + CMP ES:[arena_size],CX ; is size of best larger than found? + POP ES + JBE alloc_last +alloc_make_best: + MOV [BestArena],DS ; assign best +alloc_last: + MOV [LastArena],DS ; assign last + JMP alloc_next + +; +; split the block high +; +alloc_do_split_high: + MOV DS,[LastArena] + MOV CX,DS:[arena_size] + SUB CX,BX + MOV DX,DS + JE alloc_set_owner ; sizes are equal, no split + ADD DX,CX ; point to next block + MOV ES,DX ; no decrement! + DEC CX + XCHG BX,CX ; bx has size of lower block + JMP alloc_set_sizes ; cx has upper (requested) size + +; +; we have scanned memory and have found all appropriate blocks +; check for the type of allocation desired; first and best are identical +; last must be split high +; +alloc_do_split: + CMP BYTE PTR [AllocMethod], 1 + JA alloc_do_split_high + MOV DS,[FirstArena] + JB alloc_get_size + MOV DS,[BestArena] +alloc_get_size: + MOV CX,DS:[arena_size] + SUB CX,BX ; get room left over + MOV AX,DS + MOV DX,AX ; save for owner setting + JE alloc_set_owner ; IF BX = size THEN (don't split) + ADD AX,BX + INC AX ; remember the header + MOV ES,AX ; ES <- DS + BX (new header location) + DEC CX ; CX <- size of split block +alloc_set_sizes: + MOV DS:[arena_size],BX ; current size <- BX + MOV ES:[arena_size],CX ; split size <- CX + MOV BL,arena_signature_normal + XCHG BL,DS:[DI] ; current signature <- 4D + MOV ES:[DI],BL ; new block sig <- old block sig + MOV ES:[arena_owner],DI + +alloc_set_owner: + MOV DS,DX + MOV AX,[CurrentPDB] + MOV DS:[arena_owner],AX + MOV AX,DS + INC AX + POP BX + LeaveCrit critMem + transfer SYS_RET_OK + +EndProc $alloc + +SUBTTL $SETBLOCK - change size of an allocated block (if possible) +PAGE +; +; Assembler usage: +; MOV ES,block +; MOV BX,newsize +; MOV AH,setblock +; INT 21h +; if setblock fails for growing, BX will have the maximum +; size possible +; Error return: +; AX = error_invalid_block +; = error_arena_trashed +; = error_not_enough_memory +; = error_invalid_function +; + procedure $SETBLOCK,NEAR + ASSUME DS:NOTHING,ES:NOTHING + EnterCrit critMem + MOV DI,arena_signature + MOV AX,ES + DEC AX + CALL check_signature + JNC setblock_grab + +setblock_bad: + JMP alloc_trashed + +setblock_grab: + MOV DS,AX + CALL coalesce + JC setblock_bad + MOV CX,DS:[arena_size] + PUSH CX + CMP BX,CX + JBE alloc_get_size + JMP alloc_fail +EndProc $setblock + +SUBTTL $DEALLOC - free previously allocated piece of memory +PAGE +; +; Assembler usage: +; MOV ES,block +; MOV AH,dealloc +; INT 21h +; +; Error return: +; AX = error_invalid_block +; = error_arena_trashed +; + procedure $DEALLOC,NEAR + ASSUME DS:NOTHING,ES:NOTHING + EnterCrit critMem + MOV DI,arena_signature + MOV AX,ES + DEC AX + CALL check_signature + JC dealloc_err + MOV ES:[arena_owner],DI + LeaveCrit critMem + transfer SYS_RET_OK + +dealloc_err: + LeaveCrit critMem + error error_invalid_block +EndProc $DEALLOC + +SUBTTL $AllocOper - get/set allocation mechanism +PAGE +; +; Assembler usage: +; MOV AH,AllocOper +; MOV BX,method +; MOV AL,func +; INT 21h +; +; Error return: +; AX = error_invalid_function +; + procedure $AllocOper,NEAR + ASSUME DS:NOTHING,ES:NOTHING + CMP AL,1 + JB AllocOperGet + JZ AllocOperSet + MOV EXTERR_LOCUS,errLoc_mem ; Extended Error Locus + error error_invalid_function +AllocOperGet: + MOV AL,BYTE PTR [AllocMethod] + XOR AH,AH + transfer SYS_RET_OK +AllocOperSet: + MOV [AllocMethod],BL + transfer SYS_RET_OK +EndProc $AllocOper + +CODE ENDS + END diff --git a/v4.0/src/DOS/BUF.ASM b/v4.0/src/DOS/BUF.ASM new file mode 100644 index 0000000..f6a6b7d --- /dev/null +++ b/v4.0/src/DOS/BUF.ASM @@ -0,0 +1,982 @@ +; SCCSID = @(#)buf.asm 1.1 85/04/09 +TITLE BUF - MSDOS buffer management +NAME BUF +; Low level routines for buffer cache management +; +; GETCURHEAD +; SET_MAP_PAGE +; SAVE_MAP +; RESTORE_MAP +; SETVISIT +; ScanPlace +; PLACEBUF +; PLACEHEAD +; PointComp +; GETBUFFR +; GETBUFFRB +; FlushBuf +; BufWrite +; SKIPVISIT +; SET_RQ_SC_PARMS +; +; Revision history: +; +; AN000 version 4.00 Jan. 1988 +; A004 PTM 3765 -- Disk reset failed + +; NEW PROCS FOR BUFFERS FIX: + +; SAVE_USER_MAP +; RESTORE_USER_MAP +; DETECT_COLLISION +; SETUP_EMS_BUFFERS +; + + +; +; get the appropriate segment definitions +; +.xlist +INCLUDE dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +include version.inc +.cref +.list + +Installed = TRUE + + i_need BuffHead,DWORD + i_need PreRead,WORD + i_need LastBuffer,DWORD + i_need CurBuf,DWORD + i_need WPErr,BYTE + i_need ALLOWED,BYTE + i_need FAILERR,BYTE + i_need HIGH_SECTOR,WORD ; DOS 4.00 >32mb ;AN000; + i_need CurHashEntry,DWORD ; DOS 4.00 current Hash entry ;AN000; + i_need BUF_HASH_PTR,DWORD ; DOS 4.00 Hash table pointer ;AN000; + i_need BUF_HASH_COUNT,WORD ; DOS 4.00 Hash table entries ;AN000; + i_need SC_CACHE_PTR,DWORD ; DOS 4.00 seconadary cache table ;AN000; + i_need SC_CACHE_COUNT,WORD ; DOS 4.00 secondary cache entries ;AN000; + i_need BUF_EMS_MODE,BYTE ; DOS 4.00 EMS mode ;AN000; + i_need BUF_EMS_HANDLE,WORD ; DOS 4.00 buffer EMS handle ;AN000; + i_need SC_SECTOR_SIZE,WORD ; DOS 4.00 sector size ;AN000; + i_need SC_DRIVE,BYTE ; DOS 4.00 drive ;AN000; + i_need ACT_PAGE,WORD ; DOS 4.00 active logical EMS page ;AN000; + i_need DOS34_FLAG,WORD ; DOS 4.00 common flag ;AN000; + i_need BUF_EMS_SEG_CNT,WORD ; DOS 4.00 EMS seg count ;AN000; + i_need BUF_EMS_MAP_BUFF,BYTE ; DOS 4.00 EMS map buffer ;AN000; + i_need FIRST_BUFF_ADDR,WORD ; DOS 4.00 beginning of the chain ;AN000; + i_need BUF_EMS_PAGE_FRAME,WORD ; DOS 4.00 EMS page frame ;AN000; + +IF BUFFERFLAG + i_need BUF_EMS_PFRAME,WORD + i_need BUF_EMS_LAST_PAGE,WORD + i_need BUF_EMS_FIRST_PAGE,WORD + i_need BUF_EMS_SAFE_FLAG,byte + i_need BUF_EMS_NPA640,WORD + i_need NEXTADD,WORD + i_need DMAADD,DWORD + i_need BYTCNT1,WORD + i_am BUF_EMS_MAP_BUF,12,<0,0,0,0,0,0,0,0,0,0,0,0> + i_am CURADD,WORD + i_am low_ems_buf,512 + extrn SAVE_USER_MAP:near + extrn RESTORE_USER_MAP:near +ENDIF + + +Break + +; Inputs: +; DX= sector number (LOW) +; [HIGH_SECTOR]= sector number (HIGH) +; Function: +; Hash into a buffer group and activate the extended memory if +; necessary +; Outputs: +; [CurHashEntry] = current Hash entry addr +; DS:DI = 1st buffer addr of the current Hash entry +; No other registers altered + + procedure GETCURHEAD,NEAR + ASSUME DS:NOTHING,ES:NOTHING + + PUSH DX ;LB. save regs ;AN000; + PUSH AX ;LB. ;AN000; + PUSH BX ;LB. ;AN000; + MOV AX,DX ;LB. ;AN000; +; MOV DX,[HIGH_SECTOR] ;LB. HASH(sector#) and get entry # ;AN000; + XOR DX,DX ;LB. to avoid divide overflow ;AN000; + DIV [BUF_HASH_COUNT] ;LB. get remainder ;AN000; + ADD DX,DX ;LB. 8 bytes per entry ;AN000; + ADD DX,DX ;LB. ;AN000; + ADD DX,DX ;LB. times 8 ;AN000; + + LDS DI,[BUF_HASH_PTR] ;LB. get Hash Table addr ;AN000; + ADD DI,DX ;LB position to entry ;AN000; +Map_Entry2: + MOV WORD PTR [CurHashEntry+2],DS ;LB. update current Hash entry ptr ;AN000; + MOV WORD PTR [CurHashEntry],DI ;LB. ;AN000; + MOV WORD PTR [LASTBUFFER],-1 ;LB. invalidate last buffer ;AN000; + MOV BX,[DI.EMS_PAGE_NUM] ;LB. logical page ;AN000; + +IF NOT BUFFERFLAG + LDS DI,[DI.BUFFER_BUCKET] ;LB. ds:di is 1st buffer addr ;AN000; + MOV [FIRST_BUFF_ADDR],DI ;LB. 1/19/88 save first buffer addr ;AN000; + CALL SET_MAP_PAGE ;LB. activate handle if EMS there ;AN000; +ELSE + push ax + mov ax, [NEXTADD] + mov [CURADD], ax + pop ax + CALL SET_MAP_PAGE ;LB. activate handle if EMS there ;AN000; + LDS DI,[DI.BUFFER_BUCKET] ;LB. ds:di is 1st buffer addr ;AN000; + MOV [FIRST_BUFF_ADDR],DI ;LB. 1/19/88 save first buffer addr ;AN000; +ENDIF + + ;AN000; + POP BX ;LB. ;AN000; + POP AX ;LB. ;AN000; + POP DX ;LB. ;AN000; + return ;LB. ;AN000; +EndProc GETCURHEAD ;AN000; + + ;AN000; +Break ;AN000; +; Inputs: ;AN000; +; BX= logical page ;AN000; +; Function: ;AN000; +; Map handle and logical page to frame 0 page 0 ;AN000; +; Outputs: ;AN000; +; AH=0 success ;AN000; +; No other registers altered ;AN000; + ;AN000; +Procedure SET_MAP_PAGE,NEAR ;AN000; + ASSUME DS:NOTHING,ES:NOTHING ;AN000; + +; int 3 + ;AN000; + CMP [BUF_EMS_MODE],-1 ;LB. EMS support ;AN000; + JZ No_map ;LB. no ;AN000; + +IF NOT BUFFERFLAG + CMP [ACT_PAGE],BX ;LB. already mapped ? ;AN000; + JZ No_map ;LB. yes ;AN000; +ENDIF + MOV [ACT_PAGE],BX ;LB. save active page mapped ;AN000; + +IF BUFFERFLAG + cmp [BUF_EMS_SAFE_FLAG], 1 + je no_coll +; int 3 + call detect_collision +no_coll: +ENDIF + + MOV DX,[BUF_EMS_HANDLE] ;LB. ;AN000; + MOV AH,44H ;LB. activate current handle ;AN000; + MOV AL,BYTE PTR [BUF_EMS_PAGE_FRAME] ;LB. page frame number ;AN000; + INT 67H ;LB. ;AN000; +No_map: ;AN000; + return ;AN000; +EndProc SET_MAP_PAGE ;AN000; + ;AN000; + +IF BUFFERFLAG + +Break ;AN000; +; Inputs: ;AN000; +; none ;AN000; +; Function: ;AN000; +; save map ;AN000; +; Outputs: ;AN000; +; none ;AN000; +; No other registers altered ;AN000; + ;AN000; +Procedure SAVE_MAP,NEAR ;AN000; + ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; + CMP [BUF_EMS_MODE],-1 ;LB. EMS support ;AN000; + JZ No_save ;LB. no ;AN000; + MOV [ACT_PAGE],-1 ;LB. invalidate active page ;AN000; + MOV WORD PTR [LASTBUFFER],-1 ;LB. and last buffer pointer ;AN000; + PUSH AX ;LB. save regs ;AN000; + PUSH DS ;LB. save regs ;AN000; + PUSH ES ;LB. ;AN000; + PUSH SI ;LB. ;AN000; + PUSH DI ;LB. ;AN000; + MOV SI,OFFSET DOSGROUP:BUF_EMS_SEG_CNT ;LB. ;AN000; + MOV DI,OFFSET DOSGROUP:BUF_EMS_MAP_BUF ;LB. ;AN000; + + PUSH CS + POP ES + PUSH CS ;LB. ;AN000; + POP DS ;LB. ds:si -> ems seg count ;AN000; + + MOV AX,4F00H ;LB. save map ;AN000; + EnterCrit critDisk ;LB. enter critical section ;AN000; + INT 67H ;LB. ;AN000; + LeaveCrit critDisk ;LB. leave critical section ;AN000; + POP DI ;LB. ;AN000; + POP SI ;LB. restore regs ;AN000; + POP ES ;LB. ;AN000; + POP DS ;LB. ;AN000; + POP AX ;LB. restore ;AN000; +No_save: ;AN000; + return ;AN000; +EndProc SAVE_MAP ;AN000; + ;AN000; + +Break ;AN000; +; Inputs: ;AN000; +; none ;AN000; +; Function: ;AN000; +; restore_map ;AN000; +; Outputs: ;AN000; +; none ;AN000; +; No other registers altered ;AN000; + ;AN000; +Procedure RESTORE_MAP,NEAR ;AN000; + ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; + CMP [BUF_EMS_MODE],-1 ;LB. EMS support ;AN000; + JZ No_restore ;LB. no ;AN000; + PUSH AX ;LB. save regs ;AN000; + PUSH DS ;LB. save regs ;AN000; + PUSH SI ;LB. ;AN000; + MOV SI,OFFSET DOSGROUP:BUF_EMS_MAP_BUF ;LB. ;AN000; + + PUSH CS + POP DS + MOV AX,4F01H ;LB. restore map ;AN000; + EnterCrit critDisk ;LB. enter critical section ;AN000; + INT 67H ;LB. ;AN000; + LeaveCrit critDisk ;LB. leave critical section ;AN000; + POP SI ;LB. restore regs ;AN000; + POP DS ;LB. ;AN000; + POP AX ;LB. ;AN000; +No_restore: ;AN000; + return ;AN000; +EndProc RESTORE_MAP ;AN000; + +ENDIF + ;AN000; + ;AN000; + +Break + +; Inputs: +; Same as PLACEBUF +; Function: +; Save scan location and call PLACEBUF +; Outputs: +; DS:DI Points to saved scan location +; SI destroyed, other registers unchanged + + procedure ScanPlace,near +ASSUME DS:NOTHING,ES:NOTHING + +;; PUSH ES +;; LES SI,[DI.buf_link] ; Save scan location + MOV SI,[DI.buf_next] ; Save scan location + CALL PLACEBUF +;; PUSH ES +;; POP DS ; Restore scan location + MOV DI,SI +;; POP ES + return +EndProc ScanPlace + +; Rewritten PLACEBUF (LKR), eliminates loops +; +; Input: +; DS:DI points to buffer (DS->BUFFINFO array, DI=offset in array) +; Function: +; Remove buffer from queue and re-insert it in proper place. +; NO registers altered + + procedure PLACEBUF,NEAR +ASSUME DS:NOTHING,ES:NOTHING + +; invoke save_world + push AX ;Save only regs we modify ;AN000; + push BX ;AN000; + push SI ;AN000; + push ES ;AN000; + + les SI,[CurHashEntry] ;ES:SI -> Current Hash entry ;AN000; + mov BX,word ptr ES:[SI.BUFFER_BUCKET] ;BX = offset of head of list ;AN000; + + cmp [DI.buf_next],BX ;Buf = last? ;AN000; + je nret ;Yes, special case ;AN000; + cmp DI,BX ;Buf = first? ;AN000; + je bufloop ;Yes, special case ;AN000; + mov SI,[DI.buf_prev] ;No, SI = prior Buf ;AN000; + mov AX,[DI.buf_next] ;Now delete Buf from list ;AN000; + mov [SI.buf_next],AX ;AN000; + push SI ;Save si ;AN000; + mov SI,[DI.buf_next] ;Update backward pointer ;AN000; + mov AX,[DI.buf_prev] ; ;AN000; + mov [SI.buf_prev],AX ; ;AN000; + pop si ;Restore si ;AN000; +lookend: ;(label is now a misnomer) ;AN000; + mov SI,[BX.buf_prev] ;SI-> last buffer ;AN000; + mov [SI.buf_next],DI ;Add Buf to end of list ;AN000; + mov [BX.buf_prev],DI ;AN000; + mov [DI.buf_prev],SI ;Update linkage in Buf too ;AN000; + mov [DI.buf_next],BX ;AN000; +nret: ;AN000; + ;AN000; +; invoke restore_world ;AN000; + pop ES ;Restore regs we modified ;AN000; + pop SI ;AN000; + pop BX ;AN000; + pop AX ;AN000; + ;AN000; + cmp [DI.buf_ID],-1 ; Buffer FREE? ;AN000; + retnz ; No ;AN000; + invoke PLACEHEAD ; Buffer is free, belongs at hea;AN000; + return ;AN000; +bufloop: ;(label is now a misnomer) ;AN000; + mov BX,[DI.buf_next] ;Set new head position ;AN000; + mov word ptr ES:[SI.BUFFER_BUCKET],BX ;AN000; + jmp nret ;Continue with repositioning ;AN000; + +EndProc PLACEBUF + +; SAME AS PLACEBUF except places buffer at head +; NOTE:::::: ASSUMES THAT BUFFER IS CURRENTLY THE LAST +; ONE IN THE LIST!!!!!!! +; Rewritten PLACEBUF, takes buffer from end of list to head of list + + procedure PLACEHEAD,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + push ES ;AN000; + push SI ;AN000; + les SI,[CurHashEntry] ;AN000; + mov word ptr ES:[SI.BUFFER_BUCKET],DI ;AN000; + pop SI ;AN000; + pop ES ;AN000; + return ;AN000; +EndProc PLACEHEAD ;AN000; + + +Break + +; Compare DS:SI to ES:DI (or DS:DI to ES:SI) for equality +; DO NOT USE FOR < or > +; No Registers altered + + procedure PointComp,NEAR +ASSUME DS:NOTHING,ES:NOTHING + + CMP SI,DI + retnz + PUSH CX + PUSH DX + MOV CX,DS + MOV DX,ES + CMP CX,DX + POP DX + POP CX + return +EndProc PointComp + +Break + +; Input: +; AL = 0 means sector must be pre-read +; ELSE no pre-read +; DX = Desired physical sector number (LOW) +; [HIGH_SECTOR]= Desired physical sector number (HIGH) +; ES:BP = Pointer to drive parameters +; [ALLOWED] set in case of INT 24 +; Function: +; Get the specified local sector into one of the I/O buffers +; And shuffle the queue +; Output: +; [CURBUF] Points to the Buffer for the sector +; THE BUFFER TYPE FIELD OF buf_flags = 0, caller must set it +; Carry set if error (currently user FAILed to INT 24) +; DS,DX,ES:BP unchanged, all other registers destroyed + + procedure GETBUFFR,NEAR + DOSAssume CS,,"GetBuffr" + ASSUME ES:NOTHING + + XOR SI,SI + + entry GETBUFFRB + + Assert ISDPB,,"GetBuffr" + MOV [PREREAD],AX + MOV AL,ES:[BP.dpb_drive] + LDS DI,[LASTBUFFER] +ASSUME DS:NOTHING + MOV CX,[HIGH_SECTOR] ; F.C. >32mb ;AN000; + CMP DI,-1 ; Recency pointer valid? + JZ SKBUF ; No + + CMP DX,WORD PTR [DI.buf_sector] + JNZ SKBUF ; Wrong sector + CMP CX,WORD PTR [DI.buf_sector+2] ; F.C. >32mb ;AN000; + JNZ SKBUF ; F.C. >32mb ;AN000; + CMP AL,[DI.buf_ID] + JNZ SKBUF ; Wrong Drive + + JMP JUSTBUF ; Just asked for same buffer +SKBUF: + CALL GETCURHEAD ;LB. get cuurent Hash entry ;AN000; +; LDS DI,[BUFFHEAD] +NXTBFF: + CMP DX,WORD PTR [DI.buf_sector] ; F.C. >32mb ;AN000; + JNZ BUMP + CMP CX,WORD PTR [DI.buf_sector+2] ; F.C. >32mb ;AN000; + JNZ BUMP ; F.C. >32mb ;AN000; + CMP AL,[DI.buf_ID] +if not bufferflag + JZ SETINF +else + jnz bump + jmp setinf +endif +BUMP: + mov DI,[DI.buf_next] ;;;;;;1/19/88 ;AN000; + cmp DI,[FIRST_BUFF_ADDR] ;;;;;;1/19/88 ;AN000; + JNZ NXTBFF +;;;; LDS DI,[CurHashEntry] ;LB. secondary cache's use ;AN000; +;;;; LDS DI,[DI.BUFFER_BUCKET] ;LB. ;AN000; + ; LDS DI,[BUFFHEAD] + PUSH [HIGH_SECTOR] ;F.C. >32mb ;AN000; + PUSH SI + PUSH DX + PUSH BP + PUSH ES + CALL BUFWRITE ; Write out the dirty buffer + POP ES + POP BP + POP DX + POP SI + POP [HIGH_SECTOR] ;F.C. >32mb ;AN000; +if not bufferflag + JC GETBERR +else + jnc skip_getberr + jmp getberr +skip_getberr: +endif + CALL SET_RQ_SC_PARMS ;LB. set parms ;AN000; + XOR AH,AH ; initial flags + TEST BYTE PTR [PREREAD],-1 ; Read in the new sector + JNZ SETBUF + LEA BX,[DI.BufInSiz] ; Point at buffer + MOV CX,1 + PUSH SI + PUSH DI + PUSH DX +; Note: As far as I can tell, all disk reads into buffers go through this point. -mrw 10/88 +if bufferflag +; int 3 + cmp [buf_ems_mode], -1 + jz normread + push bx + push ds ; save ds:bx --> ems_buffer + push cs + pop ds + mov bx, offset dosgroup:low_ems_buf ; ds:bx --> low_ems_buffer +normread: +endif + OR SI,SI + JZ NORMSEC + invoke FATSECRD + MOV AH,buf_isFAT ; Set buf_flags + JMP SHORT GOTTHESEC ; Buffer is marked free if read barfs +NORMSEC: + invoke DREAD ; Buffer is marked free if read barfs + MOV AH,0 ; Set buf_flags to no type, DO NOT XOR! +GOTTHESEC: ; Carry set by either FATSECRD or DREAD +if bufferflag + pushf + jc skipreadtrans + cmp [buf_ems_mode], -1 + je skipreadtrans + + popf + pop ds + pop bx ; restore ems_buffer pointer + pushf + + push cx ; save regs to be used by rep mov + push ds + push es + + mov di, bx + push ds + pop es ; es:di --> ems_buf + mov si, offset dosgroup:low_ems_buf + push cs + pop ds ; ds:si --> low_ems_buf + mov cx, 512/2 + rep movsw + + pop es ; restore regs. + pop ds + pop cx +skipreadtrans: + popf +endif + POP DX + POP DI + POP SI + JC GETBERR +SETBUF: + MOV CX,[HIGH_SECTOR] ; F.C. >32mb ;AN000; + MOV WORD PTR [DI.buf_sector+2],CX ; F.C. >32mb ;AN000; + MOV WORD PTR [DI.buf_sector],DX ; F.C. >32mb ;AN000; + MOV WORD PTR [DI.buf_DPB],BP + MOV WORD PTR [DI.buf_DPB+2],ES + MOV AL,ES:[BP.dpb_drive] + MOV WORD PTR [DI.buf_ID],AX ; Sets buf_flags too, to AH +SETINF: + MOV [DI.buf_wrtcnt],1 ; Default to not a FAT sector ;AC000; + XOR AX,AX ;>32mb ;AN000; + OR SI,SI + JZ SETSTUFFOK + MOV AL,ES:[BP.dpb_FAT_count] + MOV [DI.buf_wrtcnt],AL ;>32mb ;AN000; + MOV AX,ES:[BP.dpb_FAT_size] +SETSTUFFOK: + MOV [DI.buf_wrtcntinc],AX ;>32mb ;AC000; + CALL PLACEBUF +JUSTBUF: + MOV WORD PTR [CURBUF+2],DS + MOV WORD PTR [LASTBUFFER+2],DS + MOV WORD PTR [CURBUF],DI + MOV WORD PTR [LASTBUFFER],DI + CLC +GETBERR: + Context DS + return +EndProc GETBUFFR + +Break + +; Input: +; DS = DOSGROUP +; AL = Physical unit number local buffers only +; = -1 for all units and all remote buffers +; Function: +; Write out all dirty buffers for unit, and flag them as clean +; Carry set if error (user FAILed to I 24) +; Flush operation completed. +; DS Preserved, all others destroyed (ES too) + + procedure FlushBuf,NEAR + DOSAssume CS,,"FlushBuf" + ASSUME ES:NOTHING + + MOV AH,-1 +; LDS DI,[BUFFHEAD] +ASSUME DS:NOTHING + + LDS DI,[BUF_HASH_PTR] ;LB. get Hash Table addr ;AN000; + MOV CX,[BUF_HASH_COUNT] ;LB. get Hash entry count ;AN000; + XOR DX,DX ;LB. set initial index to 0 ;AN000; + +NXTBUFF2: + PUSH CX ;LB. save Hash entry count ;AN000; + TEST [DOS34_FLAG],FROM_DISK_RESET ;MS. from disk reset ;AN004; + JNZ Zapzap ;MS. yes ;AN004; + CMP [DI.Dirty_Count],0 ;LB. dirty entry ? ;AN000; + JZ getnext ;LB. no ;AN000; +Zapzap: ;AN004; + PUSH DS ;LB. save regs ;AN000; + PUSH DI ;LB. ;AN000; + invoke Map_Entry ;LB. ds:di -> first buffer addr ;AN000; +NXTBUFF: + CALL CHECKFLUSH ; Ignore Carry return from CHECKFLUSH. + ; FAILERR is set if user FAILed. + PUSH AX + MOV AL,[DI.buf_ID] + CMP AL,BYTE PTR [WPERR] + JZ ZAP + TEST [DOS34_FLAG],FROM_DISK_RESET ;MS. from disk reset ;AN000; + JNZ Zap ;MS. yes ;AN000; + +NOZAP: + POP AX + mov DI,[DI.buf_next] ;;;;1/19/88 ;AN000; + CMP DI,[FIRST_BUFF_ADDR] ;;;;1/19/88 ;AN000; + JNZ NXTBUFF + + POP DI ;LB. ;AN000; + POP DS ;LB. ;AN000; +getnext: + ADD DI,size BUFFER_HASH_ENTRY ;LB. position to next entry ;AN000; + POP CX ;LB. restore entry count ;AN000; + LOOP NXTBUFF2 ;LB. get next entry buffer ;AN000; + Context DS + CMP [FAILERR],0 + JNZ FLSHBad ; Carry clear if JMP + return +FlshBad: + STC ; Return error if user FAILed + return +Zap: + MOV WORD PTR [DI.buf_ID],00FFH ; Invalidate buffer, it is inconsistent + JMP NoZap + +EndProc FlushBuf + + procedure CHECKFLUSH,NEAR +ASSUME DS:NOTHING,ES:NOTHING +; Carry set if problem (currently user FAILed to I 24) + + Assert ISBUF,,"CheckFlush" + CMP [DI.buf_ID],AH + retz ; Skip free buffers, carry clear + CMP AH,AL + JZ DOBUFFER ; Do all dirty buffers + CMP AL,[DI.buf_ID] + CLC + retnz ; Buffer not for this unit or SFT +DOBUFFER: + TEST [DI.buf_flags],buf_dirty + retz ; Buffer not dirty, carry clear by TEST + PUSH AX + PUSH WORD PTR [DI.buf_ID] + CALL BUFWRITE + POP AX + JC LEAVE_BUF ; Leave buffer marked free (lost). + AND AH,NOT buf_dirty ; Buffer is clean, clears carry + MOV WORD PTR [DI.buf_ID],AX +LEAVE_BUF: + POP AX ; Search info + return +EndProc CHECKFLUSH + +Break + +; Input: +; DS:DI Points to the buffer +; Function: +; Write out all the buffer if dirty. +; Output: +; Buffer marked free +; Carry set if error (currently user FAILed to I 24) +; DS:DI Preserved, ALL others destroyed (ES too) + + procedure BufWrite,NEAR +ASSUME DS:NOTHING,ES:NOTHING + + Assert ISBUF,,"BufWrite" + MOV AX,00FFH + XCHG AX,WORD PTR [DI.buf_ID] ; Free, in case write barfs + CMP AL,0FFH + retz ; Buffer is free, carry clear. + TEST AH,buf_dirty + retz ; Buffer is clean, carry clear. + invoke DEC_DIRTY_COUNT ; LB. decrement dirty count + CMP AL,BYTE PTR [WPERR] + retz ; If in WP error zap buffer + MOV [SC_DRIVE],AL ;LB. set it for invalidation ;AN000; + LES BP,[DI.buf_DPB] + LEA BX,[DI.BufInSiz] ; Point at buffer + MOV DX,WORD PTR [DI.buf_sector] ;F.C. >32mb ;AN000; + MOV CX,WORD PTR [DI.buf_sector+2] ;F.C. >32mb ;AN000; + MOV [HIGH_SECTOR],CX ;F.C. >32mb ;AN000; + MOV CL,[DI.buf_wrtcnt] ;>32mb ;AC000; +; MOV AL,CH ; [DI.buf_wrtcntinc] + XOR CH,CH + MOV AX,[DI.buf_wrtcntinc] ;>32mb ;AC000; + MOV [ALLOWED],allowed_RETRY + allowed_FAIL + TEST [DI.buf_flags],buf_isDATA + JZ NO_IGNORE + OR [ALLOWED],allowed_IGNORE +NO_IGNORE: + PUSH DI ; Save buffer pointer + XOR DI,DI ; Indicate failure +WRTAGAIN: + SaveReg + MOV CX,1 + SaveReg +; Note: As far as I can tell, all disk reads into buffers go through this point. -mrw 10/88 + +if bufferflag +; int 3 + cmp [buf_ems_mode], -1 + jz skipwritetrans + + push es + push di + push si + push cx + + mov si, bx ; ds:si --> ems_buffer + mov di, offset dosgroup:low_ems_buf + push cs + pop es ; es:di --> low_ems_buffer + mov cx, 512/2 + rep movsw + + pop cx + pop si + pop di + pop es + + push ds + push bx + mov bx, offset dosgroup:low_ems_buf + push cs + pop ds ; ds:bx --> low_ems_buffer +skipwritetrans: +endif + + invoke DWRITE ; Write out the dirty buffer + +if bufferflag + pushf ; save carry flag from DWRITE + cmp [buf_ems_mode], -1 + jz normwrite + popf ; need to get at stack + pop bx ; ds:bx --> ems_buffer + pop ds + pushf ; put it back, so we can pop it +normwrite: + popf ; restore carry flag +endif + + RestoreReg + RestoreReg + JC NOSET + INC DI ; If at least ONE write succeedes, the operation +NOSET: ; succeedes. + ADD DX,AX + LOOP WRTAGAIN + OR DI,DI ; Clears carry + JNZ BWROK ; At least one write worked + STC ; DI never got INCed, all writes failed. +BWROK: + POP DI + return +EndProc BufWrite + +Break + +; Input: +; ES:BP = drive parameter block +; Function: +; Set requesting drive, and sector size +; Output: +; [SC_SECTOR_SIZE]= drive sector size +; [SC_DRIVE]= drive # +; +; All registers preserved + + procedure SET_RQ_SC_PARMS,NEAR +ASSUME DS:NOTHING,ES:NOTHING + + CMP [SC_CACHE_COUNT],0 ;LB. do it only secondary cache exists ;AN000; + JZ nosec ;LB. ;AN000; + PUSH DX ;LB. save dx ;AN000; + MOV DX,ES:[BP.dpb_sector_size] ;LB. save sector size ;AN000; + MOV [SC_SECTOR_SIZE],DX ;LB. ;AN000; + MOV DL,ES:[BP.dpb_drive] ;LB. save drive # ;AN000; + MOV [SC_DRIVE],DL ;LB. ;AN000; + ;AN000; + POP DX ;LB. restore dx ;AN000; + +nosec: + return +EndProc SET_RQ_SC_PARMS ;LB. return ;AN000; + +Break + +; Input: +; none +; Function: +; increment dirty buffers count +; Output: +; dirty buffers count in the current hash entry is incremented +; +; All registers preserved + + procedure INC_DIRTY_COUNT,NEAR +ASSUME DS:NOTHING,ES:NOTHING + + PUSH DS ;LB. save regs ;AN000; + PUSH SI ;LB. ;AN000; + LDS SI,[CurHashEntry] ;LB. get current hash entry ;AN000; + INC [SI.Dirty_Count] ;LB. add 1 ;AN000; + POP SI ;LB. restore regs ;AN000; + POP DS ;LB. ;AN000; + return +EndProc INC_DIRTY_COUNT ;LB. return ;AN000; + +Break + +; Input: +; none +; Function: +; decrement dirty buffers count +; Output: +; dirty buffers count in the current hash entry is decremented +; +; All registers preserved + + procedure DEC_DIRTY_COUNT,NEAR +ASSUME DS:NOTHING,ES:NOTHING + + PUSH DS ;LB. save regs ;AN000; + PUSH SI ;LB. ;AN000; + LDS SI,[CurHashEntry] ;LB. get current hash entry ;AN000; + CMP [SI.Dirty_Count],0 ;LB. in case if 0 ;AN000; + JZ nodec ;LB. do nothing ;AN000; + DEC [SI.Dirty_Count] ;LB. sub 1 ;AN000; +nodec: + POP SI ;LB. restore regs ;AN000; + POP DS ;LB. ;AN000; + return +EndProc DEC_DIRTY_COUNT ;LB. return ;AN000; + + +Break + +; Input: +; DS:DI ponits to hash entry +; Function: +; map the buferrs of this entry +; Output: +; the buffers are mapped +; +; All registers preserved + + procedure Map_Entry,NEAR +ASSUME DS:NOTHING,ES:NOTHING + + PUSH DX ;LB. save regs ;AN000; + PUSH AX ;LB. ;AN000; + PUSH BX ;LB. ;AN000; + JMP Map_Entry2 ;LB. ;AN000; +EndProc Map_Entry ;LB. ;AN000; + + +IF BUFFERFLAG + +;------------------------------------------------------------------------- +; Procedure name : detect collision +; Inputs : [DMAADD] - user Xaddr +; [CURADD] - current offset +; [BYTCNT1] - for partial sector read +; SAFE_FLAG - cleared - indicating that the +; current page is unsafe. +; +; Outputs : es - physical page segment to use +; di - corresponding page number +; SAFE_FLAG is set is a collision is detected +; and the current page is switched form +; LAST_PAGE to FIRST_PAGE. +;--------------------------------------------------------------------------- +; + +Procedure detect_collision, near +ASSUME DS:NOTHING,ES:NOTHING + + push ax + push bx + push cx + + cmp [BUF_EMS_MODE], -1 + jz fin_detect_coll + + mov ax, [CURADD] ; current offset + + cmp [BYTCNT1], 0 + je no_partial_sector + add ax, [BYTCNT1] + +no_partial_sector: + mov cl, 4 + shr ax, cl ; convert to paragraphs + mov bx, word ptr [DMAADD+2] ; get original segment + add ax, bx ; get current segment + + and ax, 0fc00h ; get ems page of current segment + cmp ax, [BUF_EMS_LAST_PAGE] ; is the current segment = last segment + jne fin_detect_coll ; page is still safe + +; int 3 + push ax + mov ax, word ptr [DMAADD] + mov ax, [NEXTADD] + mov ax, [CURADD] + mov ax, [BYTCNT1] + pop ax + + call restore_user_map + mov word ptr [LASTBUFFER], -1 + mov ax, [BUF_EMS_FIRST_PAGE] + mov [BUF_EMS_PFRAME], ax + mov ax, [BUF_EMS_FIRST_PAGE+2] + mov [BUF_EMS_PAGE_FRAME], ax + mov [BUF_EMS_SAFE_FLAG], 1 + call Setup_EMS_buffers + call save_user_map + +fin_detect_coll: + pop cx + pop bx + pop ax + ret + +EndProc detect_collision + +Procedure Setup_EMS_Buffers,Near + ASSUME DS:NOTHING,ES:NOTHING ;AN000; + + cmp [BUF_EMS_MODE], -1 + jz setup_ems_ret + + push bx + push cx + push ax + push ds + push di + + mov bx, [BUF_HASH_COUNT] ; # of hash table entries + lds di, [BUF_HASH_PTR] ; ds:di -> hash table + + xor cx, cx + +next_bucket: + mov ax, [BUF_EMS_PFRAME] + mov word ptr ds:[di.BUFFER_BUCKET+2], ax + add di, 8 ; next has entry. + inc cx + cmp cx, bx + jne next_bucket + + pop di + pop ds + pop ax + pop cx + pop bx + +setup_ems_ret: + ret + +EndProc Setup_EMS_Buffers + +ENDIF + + +CODE ENDS + END + \ No newline at end of file diff --git a/v4.0/src/DOS/CLOSE.ASM b/v4.0/src/DOS/CLOSE.ASM new file mode 100644 index 0000000..8156ac8 --- /dev/null +++ b/v4.0/src/DOS/CLOSE.ASM @@ -0,0 +1,432 @@ +; SCCSID = @(#)close.asm 1.1 85/04/09 +TITLE DOS_CLOSE/COMMIT - Internal SFT close and commit call for MSDOS +NAME DOS_CLOSE +; Internal Close and Commit calls to close a local or NET SFT. +; +; DOS_CLOSE +; DOS_COMMIT +; FREE_SFT +; SetSFTTimes +; +; Revision history: +; +; AN000 version 4.00 Jan. 1988 +; A005 PTM 3718 --- lost clusters when fastopen installed +; A011 PTM 4766 --- C2 fastopen problem + +; +; get the appropriate segment definitions +; +.xlist +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +.cref +.list + +Installed = TRUE + + I_need Attrib,BYTE + i_need THISSFT,DWORD + i_need CURBUF,DWORD + i_need THISDRV,BYTE + i_need ALLOWED,BYTE + i_need EXTERR_LOCUS,BYTE + I_need FailErr,BYTE + I_Need PROC_ID,WORD + I_Need USER_ID,WORD + i_need JShare,DWORD + i_need HIGH_SECTOR,WORD ;F.C. >32mb + i_need OLD_FIRSTCLUS,WORD ;F.O. >32mb +if debug + I_need BugLev,WORD + I_need BugTyp,WORD +include bugtyp.asm +endif + +Break + +; Inputs: +; [THISSFT] set to the SFT for the file being used +; Function: +; Close the indicated file via the SFT +; Returns: +; sf_ref_count decremented otherwise +; ES:DI point to SFT +; Carry set if error +; AX has error code +; DS preserved, others destroyed + + procedure DOS_CLOSE,NEAR + DOSAssume CS,,"DOS_Close" + ASSUME ES:NOTHING + + LES DI,[THISSFT] + Assert ISSFT,,<"DOS_CLOSE"> + fmt TypAccess,LevBUSY,<"$p: CLOSE SFT: $x:$x\n">, + MOV BX,ES:[DI.sf_flags] +; +; Network closes are handled entirely by the net code. +; + TEST BX,sf_isnet + JZ LocalClose +; invoke OWN_SHARE ;IFS. IFS owns share ? ;AN000; +; JZ noshare ;IFS. yes ;AN000; +; EnterCrit critDisk ;IFS. ;AN000; +; CALL SetSFTTimes ;IFS. set time for all SFT ;AN000; +; LeaveCrit critDisk ;IFS. ;AN000; +noshare: + CallInstall Net_Close,multnet,6 +; JC nomore ;IFS. error ;AN000; +; invoke OWN_SHARE ;IFS. IFS owns share ? ;AN000; +; JZ nomore ;IFS. yes ;AN000; +; invoke ShareEnd ;IFS. remove SFT entry from share ;AN000; +nomore: + return + +; +; All closes release the sharing information. +; No commit releases sharing information +; +; All closes decrement the ref count. +; No commit decrements the ref count. +; +LocalClose: + EnterCrit critDisk + CALL SetSFTTimes + CALL Free_SFT ; dec ref count or mark as busy + + TEST BX,devid_device ;FS. device ? ;AN000; + JNZ nofastsk ;FS. yes ;AN000; + MOV CX,ES:[DI.sf_firclus] ;FS. cx= first cluster ;AN000; + OR CX,CX ;FS. cx=0 ? ;AN000; + JZ nofastsk ;FS. yes, dont do it ;AN000; + LDS SI,ES:[DI.sf_devptr] ;FS. ;AN000; + MOV DL,[SI.dpb_drive] ;FS. dl= drive ;AN000; + invoke FastSeek_Close ;FS. invoke fastseek ;AN000; +nofastsk: + Context DS + SaveReg + invoke ShareEnd + RestoreReg +; +; Commit enters here. AX from commit MUST be <> 1, BX is flags word +; +CloseEntry: + PUSH AX +; +; File clean or device does not get stamped nor disk looked at. +; + TEST BX,devid_file_clean + devid_device + JZ rdir + JMP Free_SFT_OK ; either clean or device +; +; Retrieve the directory entry for the file +; +rdir: + CALL DirFromSFT +ASSUME DS:NOTHING + MOV AL,error_access_denied + JNC clook + JMP CloseFinish ; pretend the close worked. +clook: +; +; ES:DI points to entry +; DS:SI points to SFT +; ES:BX points to buffer header +; + SaveReg + LEA SI,[SI].sf_name +; +; ES:DI point to directory entry +; DS:SI point to unpacked name +; + invoke XCHGP +; +; ES:DI point to unpacked name +; DS:SI point to directory entry +; + invoke MetaCompare + invoke XCHGP + RestoreReg + JZ CLOSE_GO ; Name OK +Bye: MOV DI,SI + PUSH DS + POP ES ; ES:DI points to SFT + PUSH SS + POP DS + STC + MOV AL,error_file_not_found + JMP CloseFinish + +CLOSE_GO: + TEST [SI].sf_mode,sf_isfcb ; FCB ? + JZ nofcb ; no, set dir attr, sf_attr + MOV CH,ES:[DI].dir_attr + MOV AL,[SI].sf_attr + MOV Attrib,AL + invoke MatchAttributes + JNZ Bye ; attributes do not match + JMP SHORT setattr ;FT. +nofcb: + MOV AL,[SI].sf_attr ;FT. ;AN000; + MOV ES:[DI].dir_attr,AL ;FT. ;AN000; +setattr: + OR BYTE PTR ES:[DI.dir_attr],attr_archive ;Set archive + MOV AX,ES:[DI.dir_first] ;AN011;F.O. save old first clusetr + MOV [OLD_FIRSTCLUS],AX ;AN011;F.O. save old first clusetr + + MOV AX,[SI.sf_firclus] + MOV ES:[DI.dir_first],AX ;Set firclus pointer + MOV AX,WORD PTR [SI.sf_size] + MOV ES:[DI.dir_size_l],AX ;Set size + MOV AX,WORD PTR [SI.sf_size+2] + MOV ES:[DI.dir_size_h],AX + MOV AX,[SI.sf_date] + MOV ES:[DI.dir_date],AX ;Set date + MOV AX,[SI.sf_time] + MOV ES:[DI.dir_time],AX ;Set time +;; File Tagging + +; MOV AX,[SI.sf_codepage] ;AN000; +; MOV ES:[DI.dir_codepg],AX ;AN000;Set code page +; MOV AX,[SI.sf_extcluster] ;AN000; +; MOV ES:[DI.dir_extcluster],AX ;AN000; ;Set XA cluster +; MOV AL,[SI.sf_attr_hi] ;AN000; +; MOV ES:[DI.dir_attr2],AL ;AN000; ;Set high attr + +;; File Tagging + TEST ES:[BX.buf_flags],buf_dirty ;LB. if already dirty ;AN000; + JNZ yesdirty ;LB. don't increment dirty count ;AN000; + invoke INC_DIRTY_COUNT ;LB. ;AN000; + OR ES:[BX.buf_flags],buf_dirty ;Buffer dirty +yesdirty: + SaveReg + MOV CX,[SI.sf_firclus] ; do this for Fastopen + MOV AL,[THISDRV] +;;; 10/1/86 update fastopen cache + PUSH DX + MOV AH,0 ; dir entry update + MOV DL,AL ; drive number A=0, B=1,,, + OR CX,CX ;AN005; first cluster 0; may be truncated + JNZ do_update2 ;AN005; no, do update + MOV AH,3 ;AN005; do a delete cache entry + MOV DI,WORD PTR [SI.sf_dirsec] ;AN005; cx:di = dir sector + MOV CX,WORD PTR [SI.sf_dirsec+2] ;AN005; + MOV DH,[SI.sf_dirpos] ;AN005; dh= dir pos + JMP SHORT do_update ;AN011;F.O. +do_update2: ;AN011;F.O. + CMP CX,[OLD_FIRSTCLUS] ;AN011;F.O. same as old first clusetr? + JZ do_update ;AN011;F.O. yes + MOV AH,2 ;AN011;F.O. delete the old entry + MOV CX,[OLD_FIRSTCLUS] ;AN011;F.O. +do_update: ;AN005; + Context DS + invoke FastOpen_Update ; invoke fastopen + POP DX + +;;; 10/1/86 update fastopen cache + invoke FLUSHBUF ; flush all relevant buffers + RestoreReg + MOV AL,error_access_denied + JC CloseFinish +FREE_SFT_OK: + CLC ; signal no error. +CloseFinish: +; +; Indicate to the device that the SFT is being closed. +; +;;;; 7/21/86 + PUSHF ; save flag from DirFromSFT + invoke Dev_Close_SFT + POPF +;;;; 7/21/86 +; +; See if the ref count indicates that we have busied the SFT. If so, mark the +; SFT as being free. Note that we do NOT need to be in critSFT as we are ONLY +; going to be moving from busy to free. +; + POP CX ; get old ref count + PUSHF + fmt TypAccess,LevBUSY,<"$p: DOSFreeSFT: $x:$x from $x\n">, + DEC CX ; if cx != 1 + JNZ NoFree ; then do NOT free SFT + Assert ISSFT,,"DOS_FREE_SFT" + MOV ES:[DI].sf_ref_Count,CX +NoFree: + LeaveCrit critDisk + POPF + return +EndProc DOS_Close + +; +; ES:DI -> SFT. Decs sft_ref_count. If the count goes to 0, mark it as busy. +; Flags preserved. Return old ref count in AX +; +; Note that busy is indicated by the SFT ref count being -1. +; +Procedure FREE_SFT,NEAR + DOSAssume CS,,"Free_SFT" + ASSUME ES:NOTHING + + PUSHF ; Save carry state + MOV AX,ES:[DI.sf_ref_count] + DEC AX + JNZ SetCount + DEC AX +SetCount: + XCHG AX,ES:[DI.sf_ref_count] + POPF + return + +EndProc Free_SFT + +; +; DirFromSFT - locate a directory entry given an SFT. +; +; Inputs: ES:DI point to SFT +; DS = DOSGroup +; Outputs: +; EXTERR_LOCUS = errLOC_Disk +; CurBuf points to buffer +; Carry Clear -> operation OK +; ES:DI point to entry +; ES:BX point to buffer +; DS:SI point to SFT +; Carry SET -> operation failed +; registers trashified +; Registers modified: ALL + +Procedure DirFromSFT,NEAR + ASSUME DS:DOSGroup,ES:NOTHING + + MOV [EXTERR_LOCUS],errLOC_Disk + SaveReg + MOV DX,WORD PTR ES:[DI.sf_dirsec+2] ;F.C. >32mb + MOV [HIGH_SECTOR],DX ;F.C. >32mb + MOV DX,WORD PTR ES:[DI.sf_dirsec] + + PUSH [HIGH_SECTOR] ;F.C. >32mb + PUSH DX + invoke FATREAD_SFT ; ES:BP points to DPB, [THISDRV] set + ; [THISDPB] set + POP DX + POP [HIGH_SECTOR] ;F.C. >32mb + JC PopDone + XOR AL,AL ; Pre read + MOV [ALLOWED],allowed_FAIL + allowed_RETRY + invoke GETBUFFR + JC PopDone + RestoreReg ; Get back SFT pointer + ASSUME DS:NOTHING + LES DI,Curbuf + OR ES:[DI.buf_flags],buf_isDIR + MOV BX,DI ; ES:BX point to buffer header + LEA DI,[DI].BUFINSIZ ; Point to buffer + MOV AL,SIZE dir_entry + MUL [SI].sf_DirPos + ADD DI,AX ; Point at the entry + + return ; carry is clear +PopDone: + RestoreReg + return +EndProc DirFromSFT + +Break + +; Inputs: +; Same as DOS_CLOSE +; Function: +; Commit the file +; Returns: +; Same as DOS_CLOSE except ref_count field is not altered +; DS preserved, others destroyed + + procedure DOS_COMMIT,NEAR + DOSAssume CS,,"DOS_Commit" + ASSUME ES:NOTHING + + LES DI,[THISSFT] + MOV BX,ES:[DI.sf_flags] + TEST BX,devid_file_clean + devid_device ;Clears carry + retnz + TEST BX,sf_isnet + JZ LOCAL_COMMIT +IF NOT Installed + transfer NET_COMMIT +ELSE + MOV AX,(multNET SHL 8) OR 7 + INT 2FH + return +ENDIF + +; +; Perform local commit operation by doing a close but not releaseing the SFT. +; There are three ways we can do this. One is to enter a critical section to +; protect a potential free. The second is to increment the ref count to mask +; the close decrementing. +; +; The proper way is to let the caller's of close decide if a decrement should +; be done. We do this by providing another entry into close after the +; decrement and after the share information release. +; +LOCAL_COMMIT: + EnterCrit critDisk + EnterCrit critDisk ;PTM. ;AN000; + call SetSFTTimes + MOV AX,-1 + call CloseEntry + PUSHF ;PTM. ;AN000; + invoke DEV_OPEN_SFT ;PTM. increment device count ;AN000; + POPF ;PTM. ;AN000; + LeaveCrit CritDisk ;PTM. ;AN000; + return + +EndProc DOS_COMMIT + +Break + +; +; SetSFTTimes - Examine the flags for a SFT and set the time appropriately. +; Reflect these times in other SFT's for the same file. +; +; Inputs: ES:DI point to SFT +; BX = sf_flags set apprpriately +; Outputs: Set sft times to current time iff File & dirty & !nodate +; Registers modified: All except ES:DI, BX, AX +; + +Procedure SetSFTTimes,NEAR + Assert ISSFT,,"SetSFTTimes" +; +; File clean or device does not get stamped nor disk looked at. +; + TEST BX,devid_file_clean + devid_device + retnz ; clean or device => no timestamp +; +; file and dirty. See if date is good +; + TEST BX,sf_close_nodate + retnz ; nodate => no timestamp + SaveReg + invoke DATE16 ; Date/Time to AX/DX + MOV ES:[DI.sf_date],AX + MOV ES:[DI.sf_time],DX + XOR AX,AX +if installed + call JShare + 14 * 4 +else + call ShSU +endif + RestoreReg + return +EndProc SetSFTTimes + +CODE ENDS + END diff --git a/v4.0/src/DOS/CPMIO.ASM b/v4.0/src/DOS/CPMIO.ASM new file mode 100644 index 0000000..9878d4d --- /dev/null +++ b/v4.0/src/DOS/CPMIO.ASM @@ -0,0 +1,448 @@ +; SCCSID = @(#)cpmio.asm 1.1 85/04/10 +TITLE CPMIO - device IO for MSDOS +NAME CPMIO +; +; Standard device IO for MSDOS (first 12 function calls) +; + +.xlist +.xcref +include dosseg.asm +.cref +.list + +; +; Old style CP/M 1-12 system calls to talk to reserved devices +; +; $Std_Con_Input_No_Echo +; $Std_Con_String_Output +; $Std_Con_String_Input +; $RawConIO +; $RawConInput +; RAWOUT +; RAWOUT2 +; +; Revision history: +; +; A000 version 4.00 - Jan 1988 +; A002 PTM -- dir >lpt3 hangs +; +; +; +; +; +; +; +; +; +; + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +.xlist +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +include doscntry.inc ;AN000 2/12/KK +.list +.cref + +IFNDEF KANJI +KANJI EQU 0 ;FALSE +ENDIF + +; The following routines form the console I/O group (funcs 1,2,6,7,8,9,10,11). +; They assume ES and DS NOTHING, while not strictly correct, this forces data +; references to be SS or CS relative which is desired. + + i_need CARPOS,BYTE + i_need STARTPOS,BYTE + i_need INBUF,128 + i_need INSMODE,BYTE + i_need user_SP,WORD + EXTRN EscChar:BYTE ; lead byte for function keys + EXTRN CanChar:BYTE ; Cancel character + EXTRN OUTCHA:NEAR ;AN000 char out with status check 2/11/KK + i_need Printer_Flag,BYTE + i_need SCAN_FLAG,BYTE + i_need DATE_FLAG,WORD + i_need Packet_Temp,WORD ; temporary packet used by readtime + i_need DEVCALL,DWORD + i_need InterChar,BYTE ;AN000;interim char flag ( 0 = regular char) + i_need InterCon,BYTE ;AN000;console flag ( 1 = in interim mode ) + i_need SaveCurFlg,BYTE ;AN000;console out ( 1 = print and do not advance) + i_need COUNTRY_CDPG,byte ;AN000; 2/12/KK + i_need TEMP_VAR,WORD ;AN000; 2/12/KK + i_need DOS34_FLAG,WORD ;AN000; 2/12/KK + + + +Break + IF DBCS ;AN000; + +;-------------------------------- Start of Korean Support 2/11/KK + procedure $STD_CON_INPUT_NO_ECHO,NEAR ;System call 8 ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + +StdCILop: ;AN000; + invoke INTER_CON_INPUT_NO_ECHO ;AN000; + transfer InterApRet ; go to return fuction ;AN000; + +EndProc $STD_CON_INPUT_NO_ECHO ;AN000; + + procedure INTER_CON_INPUT_NO_ECHO,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; +;-----------------------------------End of Korean Support 2/11/KK + +; Inputs: +; None +; Function: +; Same as $STD_CON_INPUT_NO_ECHO but uses interim character read from +; the device. +; Returns: +; AL = character +; Zero flag SET if interim character, RESET otherwise + + ELSE ;AN000; + + +; +; Inputs: +; None +; Function: +; Input character from console, no echo +; Returns: +; AL = character + + procedure $STD_CON_INPUT_NO_ECHO,NEAR ;System call 8 +ASSUME DS:NOTHING,ES:NOTHING + + ENDIF + PUSH DS + PUSH SI +INTEST: + invoke STATCHK + JNZ Get +;************************************************************************* + cmp [Printer_Flag],0 ; is printer idle? + jnz no_sys_wait + mov ah,5 ; get input status with system wait + invoke IOFUNC +no_sys_wait: +;************************************************************************** + MOV AH,84h + INT int_IBM + +;;; 7/15/86 update the date in the idle loop +;;; Dec 19, 1986 D.C.L. changed following CMP to Byte Ptr from Word Ptr +;;;; to shorten loop in consideration of the PC Convertible + + CMP byte ptr [DATE_FLAG],-1 ; date is updated may be every + JNZ NoUpdate ; 65535 x ? ms if no one calls + PUSH AX + PUSH BX ; following is tricky, + PUSH CX ; it may be called by critical handler + PUSH DX ; at that time, DEVCALL is used by + ; other's READ or WRITE + PUSH DS ; save DS = SFT's sgement + PUSH CS ; READTIME must use DS=CS + POP DS + + MOV AX,0 ; therefore, we save DEVCALL + CALL Save_Restore_Packet ; save DEVCALL packet + invoke READTIME ; readtime + MOV AX,1 + CALL Save_Restore_Packet ; restore DEVCALL packet + + PUSH BX ; the follwing code is to + MOV BX,OFFSET DOSGROUP:DATE_FLAG + ADD BX,2 ; check the TAG + CMP word ptr CS:[BX],22642 + JZ check_ok + invoke DOSINIT ; should never come here +check_ok: + POP BX + + POP DS ; restore DS + POP DX + POP CX + POP BX + POP AX +NoUpdate: + INC [DATE_FLAG] + +;;; 7/15/86 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + JMP Intest +Get: + XOR AH,AH + invoke IOFUNC + POP SI + POP DS +;;; 7/15/86 + MOV BYTE PTR [SCAN_FLAG],0 + CMP AL,0 ; extended code ( AL ) + JNZ noscan + MOV BYTE PTR [SCAN_FLAG],1 ; set this flag for ALT_Q key + +noscan: +;;; 7/15/86 + IF DBCS ;AN000; + cmp cs:[InterChar],1 ;AN000; set the zero flag if the character3/31/KK ;AN000; + ENDIF ;AN000; + return + IF DBCS ;AN000; +EndProc INTER_CON_INPUT_NO_ECHO ;AN000; ;2/11/KK ;AN000; + ELSE ;AN000; +EndProc $STD_CON_INPUT_NO_ECHO + ENDIF ;AN000; + +Break + +; Inputs: +; DS:DX Point to output string '$' terminated +; Function: +; Print the string on the console device +; Returns: +; None + + procedure $STD_CON_STRING_OUTPUT,NEAR ;System call 9 +ASSUME DS:NOTHING,ES:NOTHING + + MOV SI,DX +STRING_OUT1: + LODSB + IF DBCS ;AN000; + invoke TESTKANJ ;AN000; 2/11/KK ;AN000; + jz SBCS00 ;AN000; 2/11/KK ;AN000; + invoke OUTT ;AN000; 2/11/KK ;AN000; + LODSB ;AN000; 2/11/KK ;AN000; + JMP NEXT_STR1 ;AN000; 2/11/KK ;AN000; +SBCS00: ;AN000; 2/11/KK ;AN000; + ENDIF ;AN000; + CMP AL,'$' + retz +NEXT_STR1: + invoke OUTT + JMP STRING_OUT1 + +EndProc $STD_CON_STRING_OUTPUT + +IF DBCS ;AN000; +include kstrin.asm ;AN000; +ELSE ;AN000; +include strin.asm +ENDIF ;AN000; + +Break + +; Inputs: +; DL = -1 if input +; else DL is output character +; Function: +; Input or output raw character from console, no echo +; Returns: +; AL = character + + procedure $RAW_CON_IO,NEAR ; System call 6 +ASSUME DS:NOTHING,ES:NOTHING + + MOV AL,DL + CMP AL,-1 + JZ RAW22 ;AN000; + JMP RAWOUT ;AN000; +RAW22: ;AN000; + LES DI,DWORD PTR [user_SP] ; Get pointer to register save area + XOR BX,BX + invoke GET_IO_SFT + retc + IF DBCS ;AN000; + push word ptr [Intercon] ;AN000; + mov [Intercon],0 ;AN000; disable interim characters + ENDIF ;AN000; + MOV AH,1 + invoke IOFUNC + JNZ RESFLG + IF DBCS ;AN000; + pop word ptr [InterCon] ;AN000; restore interim flag + ENDIF ;AN000; + invoke SPOOLINT + OR BYTE PTR ES:[DI.user_F],40H ; Set user's zero flag + XOR AL,AL + return + +RESFLG: + AND BYTE PTR ES:[DI.user_F],0FFH-40H ; Reset user's zero flag + IF DBCS ;AN000; + XOR AH,AH ;AN000; + invoke IOFUNC ;AN000; get the character + pop word ptr [InterCon] ;AN000; + return ;AN000; + ENDIF ;AN000; ;AN000; + +RILP: + invoke SPOOLINT + +; Inputs: +; None +; Function: +; Input raw character from console, no echo +; Returns: +; AL = character + + entry $RAW_CON_INPUT ; System call 7 + + PUSH BX + XOR BX,BX + invoke GET_IO_SFT + POP BX + retc + MOV AH,1 + invoke IOFUNC + JNZ Got + MOV AH,84h + INT int_IBM + JMP RILP +Got: + XOR AH,AH + invoke IOFUNC + IF DBCS ;AN000; + cmp [InterChar],1 ;AN000; 2/11/KK +; 2/11/KK +; Sets the application zero flag depending on the 2/11/KK +; zero flag upon entry to this routine. Then returns 2/11/KK +; from system call. 2/11/KK +; 2/11/KK +entry InterApRet ;AN000; 2/11/KK ;AN000; + pushf ;AN000; 3/16/KK + push ds ;AN000; 3/16/KK + push bx ;AN000; 3/16/KK + Context DS ;AN000; 3/16/KK + MOV BX,offset DOSGROUP:COUNTRY_CDPG.ccDosCodePage + cmp word ptr [bx],934 ;AN000; 3/16/KK korean code page ? + pop bx ;AN000; 3/16/KK + pop ds ;AN000; 3/16/KK + je do_koren ;AN000; 3/16/KK + popf ;AN000; 3/16/KK + return ;AN000; 3/16/KK +do_koren: ;AN000; 3/16/KK + popf ;AN000; + LES DI,DWORD PTR [user_SP] ;AN000; Get pointer to register save area KK + jnz sj0 ;AN000; 2/11/KK + OR BYTE PTR ES:[DI.user_F],40H ;AN000; Set user's zero flag 2/11/KK + return ;AN000; 2/11/KK +sj0: ;AN000; 2/11/KK + AND BYTE PTR ES:[DI.user_F],0FFH-40H ;AN000; Reset user's zero flag 2/KK + ENDIF ;AN000; + return ;AN000; +; +; Output the character in AL to stdout +; + entry RAWOUT + + PUSH BX + MOV BX,1 + + invoke GET_IO_SFT + JC RAWRET1 + + MOV BX,[SI.sf_flags] + + ; + ; If we are a network handle OR if we are not a local device then go do the + ; output the hard way. + ; + + AND BX,sf_isNet + devid_device + CMP BX,devid_device + JNZ RawNorm + IF DBCS ;AN000; + TEST [SaveCurFlg],01H ;AN000; print but no cursor adv? + JNZ RAWNORM ;AN000; 2/11/KK + ENDIF ;AN000; + +; TEST BX,sf_isnet ; output to NET? +; JNZ RAWNORM ; if so, do normally +; TEST BX,devid_device ; output to file? +; JZ RAWNORM ; if so, do normally + + PUSH DS + LDS BX,[SI.sf_devptr] ; output to special? + TEST BYTE PTR [BX+SDEVATT],ISSPEC + POP DS + JZ RAWNORM ; if not, do normally + INT int_fastcon ; quickly output the char +RAWRET: + CLC +RAWRET1: + POP BX + return +RAWNORM: + CALL RAWOUT3 + JMP RAWRET + +; +; Output the character in AL to handle in BX +; + entry RAWOUT2 + + invoke GET_IO_SFT + retc +RAWOUT3: + PUSH AX + JMP SHORT RAWOSTRT +ROLP: + invoke SPOOLINT + OR [DOS34_FLAG],CTRL_BREAK_FLAG ;AN002; set control break + invoke DSKSTATCHK ;AN002; check control break +RAWOSTRT: + MOV AH,3 + invoke IOFUNC + JZ ROLP + POP AX + MOV AH,2 + invoke IOFUNC + CLC ; Clear carry indicating successful + return +EndProc $RAW_CON_IO + +; Inputs: +; AX=0 save the DEVCALL request packet +; =1 restore the DEVCALL request packet +; Function: +; save or restore the DEVCALL packet +; Returns: +; none + + procedure Save_Restore_Packet,NEAR +ASSUME DS:NOTHING,ES:NOTHING + + PUSH DS + PUSH ES + PUSH SI + PUSH DI + CMP AX,0 ; save packet + JZ save_packet +restore_packet: + MOV SI,OFFSET DOSGROUP:Packet_Temp ;sourec + MOV DI,OFFSET DOSGROUP:DEVCALL ;destination + JMP set_seg +save_packet: + MOV DI,OFFSET DOSGROUP:Packet_Temp ;destination + MOV SI,OFFSET DOSGROUP:DEVCALL ;source +set_seg: + MOV AX,CS ; set DS,ES to DOSGROUP + MOV DS,AX + MOV ES,AX + MOV CX,11 ; 11 words to move + REP MOVSW + + POP DI + POP SI + POP ES + POP DS + return +EndProc Save_Restore_Packet + +CODE ENDS + END diff --git a/v4.0/src/DOS/CPMIO2.ASM b/v4.0/src/DOS/CPMIO2.ASM new file mode 100644 index 0000000..2b31689 --- /dev/null +++ b/v4.0/src/DOS/CPMIO2.ASM @@ -0,0 +1,354 @@ +; SCCSID = @(#)cpmio2.asm 1.1 85/04/11 +TITLE CPMIO2 - device IO for MSDOS +NAME CPMIO2 + +.xlist +.xcref +include dosseg.asm +.cref +.list + +; +; Old style CP/M 1-12 system calls to talk to reserved devices +; +; $Std_Con_Input +; $Std_Con_Output +; OUTT +; TAB +; BUFOUT +; $Std_Aux_Input +; $Std_Aux_Output +; $Std_Printer_Output +; $Std_Con_Input_Status +; $Std_Con_Input_Flush +; +; Revision History: +; +; AN000 version 4.00 - Jan. 1988 +; + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +.xlist +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +.list +.cref + +; The following routines form the console I/O group (funcs 1,2,6,7,8,9,10,11). +; They assume ES and DS NOTHING, while not strictly correct, this forces data +; references to be SS or CS relative which is desired. + + i_need CARPOS,BYTE + i_need CHARCO,BYTE + i_need PFLAG,BYTE + i_need CurrentPDB,WORD ;AN000; + i_need InterCon,BYTE ;AN000; + i_need SaveCurFlg,BYTE ;AN000; + + +Break + +; Inputs: +; None +; Function: +; Input character from console, echo +; Returns: +; AL = character + + procedure $STD_CON_INPUT,NEAR ;System call 1 +ASSUME DS:NOTHING,ES:NOTHING + + IF DBCS ;AN000; + push word ptr [InterCon] ;AN000; + mov [InterCon],01H ;AN000; + invoke INTER_CON_INPUT_NO_ECHO ;AN000; + pop word ptr [InterCon] ;AN000; + pushf ;AN000; + push AX ;AN000; + mov [SaveCurFlg],0 ;AN000; + jnz sj0 ;AN000; + mov [SaveCurFlg],1 ;AN000; +sj0: ;AN000; + invoke OUTT ;AN000; + mov [SaveCurFLg],0 ;AN000; + pop AX ;AN000; + popf ;AN000; + jz $STD_CON_INPUT ;AN000; + ELSE ;AN000; + invoke $STD_CON_INPUT_NO_ECHO + PUSH AX + invoke OUTT + POP AX + ENDIF ;AN000; + return +EndProc $STD_CON_INPUT + +Break + +; Inputs: +; DL = character +; Function: +; Output character to console +; Returns: +; None + + procedure $STD_CON_OUTPUT,NEAR ;System call 2 + public OUTCHA ;AN000; +ASSUME DS:NOTHING,ES:NOTHING + + MOV AL,DL + + entry OUTT + CMP AL,20H + JB CTRLOUT + CMP AL,c_DEL + JZ OUTCH +OUTCHA: ;AN000; + INC BYTE PTR [CARPOS] +OUTCH: + PUSH DS + PUSH SI + INC BYTE PTR [CHARCO] ;invoke statchk... + AND BYTE PTR [CHARCO],00111111B ;AN000; every 64th char + JNZ OUTSKIP + PUSH AX + invoke STATCHK + POP AX +OUTSKIP: + invoke RAWOUT ;output the character + POP SI + POP DS + IF DBCS ;AN000; + TEST [SaveCurFlg],01H ;AN000;print but no cursor adv? 2/13/KK + retnz ;AN000;if so then do not send to prt2/13/KK + ENDIF + TEST BYTE PTR [PFLAG],-1 + retz + PUSH BX + PUSH DS + PUSH SI + MOV BX,1 + invoke GET_IO_SFT + JC TRIPOPJ + MOV BX,[SI.sf_flags] + TEST BX,sf_isnet ; output to NET? + JNZ TRIPOPJ ; if so, no echo + TEST BX,devid_device ; output to file? + JZ TRIPOPJ ; if so, no echo + MOV BX,4 + invoke GET_IO_SFT + JC TRIPOPJ + TEST [SI.sf_flags],sf_net_spool ; StdPrn redirected? + JZ LISSTRT2J ; No, OK to echo + MOV BYTE PTR [PFLAG],0 ; If a spool, NEVER echo +TRIPOPJ: + JMP TRIPOP + +LISSTRT2J: + JMP LISSTRT2 + +CTRLOUT: + CMP AL,c_CR + JZ ZERPOS + CMP AL,c_BS + JZ BACKPOS + CMP AL,c_HT + JNZ OUTCH + MOV AL,[CARPOS] + OR AL,0F8H + NEG AL + + entry TAB + + PUSH CX + MOV CL,AL + MOV CH,0 + JCXZ POPTAB +TABLP: + MOV AL," " + invoke OUTT + LOOP TABLP +POPTAB: + POP CX + return + +ZERPOS: + MOV BYTE PTR [CARPOS],0 + JMP OUTCH +OUTJ: JMP OUTT + +BACKPOS: + DEC BYTE PTR [CARPOS] + JMP OUTCH + + entry BUFOUT + CMP AL," " + JAE OUTJ ;Normal char + CMP AL,9 + JZ OUTJ ;OUT knows how to expand tabs + +;DOS 3.3 7/14/86 + CMP AL,"U"-"@" ; turn ^U to section symbol + JZ CTRLU + CMP AL,"T"-"@" ; turn ^T to paragraph symbol + JZ CTRLU +NOT_CTRLU: +;DOS 3.3 7/14/86 + + PUSH AX + MOV AL,"^" + invoke OUTT ;Print '^' before control chars + POP AX + OR AL,40H ;Turn it into Upper case mate +CTRLU: + invoke OUTT + return +EndProc $STD_CON_OUTPUT + +Break + +; Inputs: +; None +; Function: +; Returns character from aux input +; Returns: +; Character in AL + + procedure $STD_AUX_INPUT,NEAR ;System call 3 +ASSUME DS:NOTHING,ES:NOTHING + + invoke STATCHK + MOV BX,3 + invoke GET_IO_SFT + retc + JMP SHORT TAISTRT +AUXILP: + invoke SPOOLINT +TAISTRT: + MOV AH,1 + invoke IOFUNC + JZ AUXILP + XOR AH,AH + invoke IOFUNC + return +EndProc $STD_AUX_INPUT + +Break + +; Inputs: +; Character in DL +; Function: +; Output character to aux output +; Returns: +; Nothing + + procedure $STD_AUX_OUTPUT,NEAR ;System call 4 +ASSUME DS:NOTHING,ES:NOTHING + + PUSH BX + MOV BX,3 + JMP SHORT SENDOUT + +EndProc $STD_AUX_OUTPUT + +Break + +; Inputs: +; DL = Character +; Function: +; Output the character to the list device +; Returns: +; None + + procedure $STD_PRINTER_OUTPUT,NEAR ;System call 5 +ASSUME DS:NOTHING,ES:NOTHING + + PUSH BX + MOV BX,4 + +SENDOUT: + MOV AL,DL + PUSH AX + invoke STATCHK + POP AX + PUSH DS + PUSH SI +LISSTRT2: + invoke RAWOUT2 +TRIPOP: + POP SI + POP DS + POP BX + return +EndProc $STD_PRINTER_OUTPUT + +Break + +; Inputs: +; None +; Function: +; Check console input status +; Returns: +; AL = -1 character available, = 0 no character + + procedure $STD_CON_INPUT_STATUS,NEAR ;System call 11 +ASSUME DS:NOTHING,ES:NOTHING + + invoke STATCHK + MOV AL,0 ; no xor!! + retz + OR AL,-1 + return +EndProc $STD_CON_INPUT_STATUS + +Break + +; Inputs: +; AL = DOS function to be called after flush (1,6,7,8,10) +; Function: +; Flush console input buffer and perform call in AL +; Returns: +; Whatever call in AL returns or AL=0 if AL was not 1,6,7,8 or 10 + + procedure $STD_CON_INPUT_FLUSH,NEAR ;System call 12 +ASSUME DS:NOTHING,ES:NOTHING + + PUSH AX + PUSH DX + XOR BX,BX + invoke GET_IO_SFT + JC BADJFNCON + MOV AH,4 + invoke IOFUNC + +BADJFNCON: + POP DX + POP AX + MOV AH,AL + CMP AL,1 + JZ REDISPJ + CMP AL,6 + JZ REDISPJ + CMP AL,7 + JZ REDISPJ + CMP AL,8 + JZ REDISPJ + CMP AL,10 + JZ REDISPJ + MOV AL,0 + return + +REDISPJ: + IF DBCS ;AN000; + mov ds,[CurrentPDB] ;AN000; + ;AN000; set DS same as one from COMMAND entry + ENDIF + CLI + transfer REDISP +EndProc $STD_CON_INPUT_FLUSH + +CODE ENDS + END diff --git a/v4.0/src/DOS/CREATE.ASM b/v4.0/src/DOS/CREATE.ASM new file mode 100644 index 0000000..6983e29 --- /dev/null +++ b/v4.0/src/DOS/CREATE.ASM @@ -0,0 +1,380 @@ +; SCCSID = @(#)create.asm 1.6 85/08/19 +TITLE DOS_CREATE/DOS_CREATE_NEW - Internal CREATE calls for MS-DOS +NAME DOS_CREATE +; Internal Create and Create new to create a local or NET file and SFT. +; +; DOS_CREATE +; DOS_CREATE_NEW +; SET_MKND_ERR +; SET_Media_ID +; SET_EXT_Mode +; +; Revision history: +; +; A000 version 4.00 Jan. 1988 +; A001 D490 -- Change IOCTL subfunctios from 63h,43h to 66h, 46h + +; +; get the appropriate segment definitions +; +.xlist +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +include version.inc +.cref +.list + +Installed = TRUE + + i_need NoSetDir,BYTE + i_need THISSFT,DWORD + i_need THISCDS,DWORD + I_need EXTERR,WORD + I_Need ExtErr_locus,BYTE + I_need JShare,DWORD + I_need VOLCHNG_FLAG,BYTE + I_need SATTRIB,BYTE + I_need CALLVIDM,DWORD + I_need OpenBuf,128 + I_need EXTOPEN_ON,BYTE ;AN000; extended open + I_need NAME1,BYTE ;AN000; + I_need NO_NAME_ID,BYTE ;AN000; + I_need Packet_Temp,WORD ;AN000; + I_need DOS34_FLAG,WORD ;AN000; + I_need SAVE_BX,WORD ;AN000; + +; Inputs: +; [WFP_START] Points to WFP string ("d:/" must be first 3 chars, NUL +; terminated) +; [CURR_DIR_END] Points to end of Current dir part of string +; ( = -1 if current dir not involved, else +; Points to first char after last "/" of current dir part) +; [THISCDS] Points to CDS being used +; (Low word = -1 if NUL CDS (Net direct request)) +; [THISSFT] Points to SFT to fill in if file created +; (sf_mode field set so that FCB may be detected) +; [SATTRIB] Is attribute of search, determines what files can be found +; AX is Attribute to create +; Function: +; Try to create the specified file truncating an old one that exists +; Outputs: +; sf_ref_count is NOT altered +; CARRY CLEAR +; THISSFT filled in. +; sf_mode = unchanged for FCB, sharing_compat + open_for_both +; CARRY SET +; AX is error code +; error_path_not_found +; Bad path (not in curr dir part if present) +; error_bad_curr_dir +; Bad path in current directory part of path +; error_access_denied +; Attempt to re-create read only file , or +; create a second volume id or create a dir +; error_sharing_violation +; The sharing mode was correct but not allowed +; generates an INT 24 +; DS preserved, others destroyed + + procedure DOS_Create,NEAR + DOSAssume CS,,"DOS_Create" + ASSUME ES:NOTHING + + XOR AH,AH ; Truncate is OK +Create_inter: + TEST AL,NOT (attr_all + attr_ignore + attr_volume_id) + ; Mask out any meaningless bits + JNZ AttErr + TEST AL,attr_volume_id + JZ NoReset + OR [DOS34_FLAG],DBCS_VOLID ;AN000;FOR dbcs volid + MOV AL,attr_volume_id +NoReset: + OR AL,attr_archive ; File changed + TEST AL,attr_directory + attr_device + JZ ATT_OK +AttErr: + MOV AX,5 ; Attribute problem + MOV Exterr_Locus,errLOC_Unk + JMP SHORT SET_MKND_ERR ; Gotta use MKDIR to make dirs, NEVER allow + ; attr_device to be set. +ATT_OK: + LES DI,[THISSFT] + PUSH ES + LES SI,[THISCDS] + CMP SI,-1 + JNZ TEST_RE_NET + POP ES + +;Extended open hooks + TEST [EXTOPEN_ON],ext_open_on ;AN000;EO. from extnded open + JZ NOEXTOP ;AN000;EO. no, do normal +IFS_extopen: ;AN000;EO. + PUSH AX ;AN000;EO. pass create attr + MOV AX,(multNET SHL 8) OR 46 ;AN000;EO. issue extended open verb + INT 2FH ;AN000;EO. + POP BX ;AN000;EO. trash bx + MOV [EXTOPEN_ON],0 ;AN000;EO. + return ;AN000;EO. +NOEXTOP: ;AN000; +;Extended open hooks + +IF NOT Installed + transfer NET_SEQ_CREATE +ELSE + PUSH AX + MOV AX,(multNET SHL 8) OR 24 + INT 2FH + POP BX ; BX is trashed anyway + return +ENDIF + +TEST_RE_NET: + TEST ES:[SI.curdir_flags],curdir_isnet + POP ES + JZ LOCAL_CREATE + + CALL Set_EXT_mode ;AN000;EO. + JC SHORT dochk ;AN000;EO. + OR ES:[DI.sf_mode],sharing_compat + open_for_both ;IFS. +dochk: + ; invoke IFS_SHARE_CHECK ;AN000;IFS. check share + ; JC nomore ;AN000;IFS. share violation + +;Extended open hooks + TEST [EXTOPEN_ON],ext_open_on ;AN000;EO. from extnded open + JNZ IFS_extopen ;AN000;EO. yes, issue extended open +;Extended open hooks + +IF NOT Installed + transfer NET_CREATE +ELSE + PUSH AX + MOV AX,(multNET SHL 8) OR 23 + INT 2FH + POP BX ; BX is trashed anyway +nomore: + return +ENDIF + +LOCAL_CREATE: + CALL Set_EXT_mode ;AN000;EO. set mode if from extended open + JC setdone ;AN000;EO. + OR ES:[DI].sf_mode,sharing_compat+open_for_both +setdone: + EnterCrit critDisk + invoke MakeNode + JNC Create_ok + mov [VOLCHNG_FLAG],-1 ; indicate no change in volume label + LeaveCrit critDisk + + entry SET_MKND_ERR + DOSAssume CS,,"Set_MkNd_Err" + ASSUME ES:NOTHING +; Looks up MakeNode errors and converts them. AL is MakeNode +; error, SI is GetPath bad spot return if path_not_found error. + + MOV BX,OFFSET DOSGROUP:CRTERRTAB + XLAT +CreatBadRet: + STC + return + +TABLE SEGMENT +Public CREAT001S,CREAT001E +CREAT001S label byte +CRTERRTAB LABEL BYTE ; Lookup table for MakeNode returns + DB ? ; none + DB error_access_denied ; MakeNode error 1 + DB error_cannot_make ; MakeNode error 2 + DB error_file_exists ; MakeNode error 3 + DB error_path_not_found ; MakeNode error 4 + DB error_access_denied ; MakeNode error 5 + DB error_sharing_violation ; MakeNode error 6 + DB error_file_not_found ; MakeNode error 7 +CREAT001E label byte +TABLE ENDS + +; +; We have just created a new file. This results in the truncation of old +; files. We must inform the sharer to slash all the open SFT's for this +; file to the current size. +; +Create_ok: +; If we created a volume id on the diskette, set the VOLCHNG_FLAG to logical +; drive number to force a Build BPB after Media Check. + +;;; FASTOPEN 8/29/86 + invoke FastOpen_Delete +;;; FASTOPEN 8/29/86 + mov al,[SATTRIB] + test al,attr_volume_id + jz NoVolLabel + LES DI,[THISCDS] + mov ah,byte ptr ES:[DI] ; get drive letter + sub ah,'A' ; convert to drive letter + mov [VOLCHNG_FLAG],ah ;Set flag to indicate volid change + MOV BH,1 ;AN000;>32mb set volume id to boot record + CALL Set_Media_ID ;AN000;>32mb + + EnterCrit CritDisk + invoke FatRead_CDS ; force a media check + LeaveCrit CritDisk +NoVolLabel: + MOV ax,2 + LES DI,ThisSFT +if installed + call JShare + 14 * 4 +else + Call ShSU +endif + LeaveCrit critDisk + transfer SET_SFT_MODE + +EndProc DOS_Create + +; Inputs: +; [WFP_START] Points to WFP string ("d:/" must be first 3 chars, NUL +; terminated) +; [CURR_DIR_END] Points to end of Current dir part of string +; ( = -1 if current dir not involved, else +; Points to first char after last "/" of current dir part) +; [THISCDS] Points to CDS being used +; (Low word = -1 if NUL CDS (Net direct request)) +; [THISSFT] Points to SFT to fill in if file created +; (sf_mode field set so that FCB may be detected) +; [SATTRIB] Is attribute of search, determines what files can be found +; AX is Attribute to create +; Function: +; Try to create the specified file truncating an old one that exists +; Outputs: +; sf_ref_count is NOT altered +; CARRY CLEAR +; THISSFT filled in. +; sf_mode = sharing_compat + open_for_both for Non-FCB SFT +; CARRY SET +; AX is error code +; error_path_not_found +; Bad path (not in curr dir part if present) +; error_bad_curr_dir +; Bad path in current directory part of path +; error_access_denied +; Create a second volume id or create a dir +; error_file_exists +; Already a file by this name +; DS preserved, others destroyed + + procedure DOS_Create_New,NEAR + DOSAssume CS,,"DOS_Create_New" + ASSUME ES:NOTHING + + MOV AH,1 ; Truncate is NOT OK + JMP Create_inter + +EndProc DOS_Create_New + + +; Inputs: +; NAME1= Volume ID +; BH= 0, delete volume id +; 1, set new volume id +; DS= DOSGROUP +; Function: +; Set Volume ID to DOS 4.00 Boot record. +; Outputs: +; CARRY CLEAR +; volume id set +; CARRY SET +; AX is error code + + procedure Set_Media_ID,NEAR ;AN000; + DOSAssume CS,,"DOS_Create_New" ;AN000; + ASSUME ES:NOTHING ;AN000; + + PUSH AX ;AN000;;>32mb + PUSH ES ;AN000;;>32mb + PUSH DI ;AN000;;>32mb + + INC AH ;AN000;;>32mb bl=drive # + MOV BL,AH ;AN000;;>32mb bl=drive # (A=1,B=2,,,) + MOV AL,0DH ;AN000;;>32mb generic IOCTL + MOV CX,0866H ;AN001;;>32mb get media id + MOV DX,OFFSET DOSGROUP:PACKET_TEMP ;AN000;>32mb + + PUSH BX ;AN000;;>32mb + PUSH DX ;AN000;;>32mb + XOR BH,BH ;AN000;;>32mb + + invoke $IOCTL ;AN000;;>32mb + POP DX ;AN000;;>32mb + POP BX ;AN000;;>32mb + JC geterr ;AN000;;>32mb + + OR BH,BH ;AN000;;>32mb delete volume id + JZ NoName ;AN000;>32mb yes + MOV SI,OFFSET DOSGROUP:NAME1 ;AN000;>32mb + JMP SHORT doset ;AN000;>32mb yes +Noname: ;AN000; + MOV SI,OFFSET DOSGROUP:NO_NAME_ID ;AN000;>32mb +doset: ;AN000; + MOV DI,DX ;AN000;;>32mb + ADD DI,MEDIA_LABEL ;AN000;;>32mb + PUSH CS ;AN000;;>32mb move new volume id to packet + POP DS ;AN000;;>32mb + PUSH CS ;AN000;;>32mb + POP ES ;AN000;;>32mb + MOV CX,11 ;AN000;;>32mb + REP MOVSB ;AN000;;>32mb + MOV CX,0846H ;AN001;;>32mb + MOV AL,0DH ;AN000;;>32mb + XOR BH,BH ;AN000;;>32mb + invoke $IOCTL ;AN000;;>32mb set volume id +geterr: ;AN000; + PUSH CS ;AN000;>32mb + POP DS ;AN000;>32mb ds= dosgroup + + POP DI ;AN000;;>32mb + POP ES ;AN000;;>32mb + POP AX ;AN000;;>32mb + return ;AN000;>32mb + +EndProc Set_Media_ID ;AN000; + + +; Inputs: +; [EXTOPEN_ON]= flag for extende open +; SAVE_BX= mode specified in Extended Open +; Function: +; Set mode in ThisSFT +; Outputs: +; carry set,mode is set if from Extended Open +; carry clear, mode not set yet + +IF NOT IBMCOPYRIGHT + public Set_EXT_mode +ENDIF + + procedure Set_EXT_mode,NEAR ;AN000; + ASSUME ES:NOTHING,DS:NOTHING ;AN000; + + TEST [EXTOPEN_ON],ext_open_on ;AN000;EO. from extnded open + JZ NOTEX ;AN000;EO. no, do normal + PUSH AX ;AN000;EO. + MOV AX,[SAVE_BX] ;AN000;EO. + OR ES:[DI.sf_mode],AX ;AN000;EO. + POP AX ;AN000;EO. + STC ;AN000;EO. +NOTEX: ;AN000; + return ;AN000;EO. + +EndProc Set_EXT_mode ;AN000; + +CODE ENDS + END + \ No newline at end of file diff --git a/v4.0/src/DOS/CRIT.ASM b/v4.0/src/DOS/CRIT.ASM new file mode 100644 index 0000000..dfb1ccd --- /dev/null +++ b/v4.0/src/DOS/CRIT.ASM @@ -0,0 +1,92 @@ +; SCCSID = @(#)crit.asm 1.1 85/04/10 +TITLE CRIT - Critical Section Routines +NAME CRIT +; +; Critical Section Routines +; +; Critical section handlers +; +; Modification history: +; +; Created: ARR 30 March 1983 +; + +.xlist +; +; get the appropriate segment definitions +; +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:NOTHING,CS:DOSGROUP + +.xcref +INCLUDE DOSSYM.INC +.cref +.list + + I_need User_In_AX,WORD + i_need CurrentPDB,WORD +if debug + I_need BugLev,WORD + I_need BugTyp,WORD +include bugtyp.asm +endif + +Break + +; +; Each handler must leave everything untouched; including flags! +; +; Sleaze for time savings: first instruction is a return. This is patched +; by the sharer to be a PUSH AX to complete the correct routines. +; +Procedure EcritDisk,NEAR + public EcritMem + public EcritSFT +ECritMEM LABEL NEAR +ECritSFT LABEL NEAR + RET +; PUSH AX + fmt TypSect,LevReq,<"PDB $x entering $x">, + MOV AX,8000h+critDisk + INT int_ibm + POP AX + return +EndProc EcritDisk + +Procedure LcritDisk,NEAR + public LcritMem + public LcritSFT +LCritMEM LABEL NEAR +LCritSFT LABEL NEAR + RET +; PUSH AX + fmt TypSect,LevReq,<"PDB $x entering $x">, + MOV AX,8100h+critDisk + INT int_ibm + POP AX + return +EndProc LcritDisk + +Procedure EcritDevice,NEAR + RET +; PUSH AX + fmt TypSect,LevReq,<"PDB $x entering $x">, + MOV AX,8000h+critDevice + INT int_ibm + POP AX + return +EndProc EcritDevice + +Procedure LcritDevice,NEAR + RET +; PUSH AX + MOV AX,8100h+critDevice + INT int_ibm + POP AX + return +EndProc LcritDevice + +CODE ENDS + END diff --git a/v4.0/src/DOS/CTRLC.ASM b/v4.0/src/DOS/CTRLC.ASM new file mode 100644 index 0000000..5a79e04 --- /dev/null +++ b/v4.0/src/DOS/CTRLC.ASM @@ -0,0 +1,771 @@ +; SCCSID = @(#)ctrlc.asm 1.4 85/08/16 +; Low level routines for detecting special characters on CON input, +; the ^C exit/int code, the Hard error INT 24 code, the +; process termination code, and the INT 0 divide overflow handler. +; +; FATAL +; FATAL1 +; reset_environment +; DSKSTATCHK +; SPOOLINT +; STATCHK +; CNTCHAND +; DIVOV +; CHARHARD +; HardErr +; +; Revision history: +; +; AN000 version 4.0 Jan 1988 +; A002 PTM -- dir >lpt3 hangs +; A003 PTM 3957- fake version for IBMCAHE.COM + +; +; get the appropriate segment definitions +; +.xlist +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +include version.inc +.cref +.list + + I_need SFN,WORD + I_NEED pJFN,DWORD + i_need DevIOBuf,BYTE + i_need DidCTRLC,BYTE + i_need INDOS,BYTE + i_need DSKSTCOM,BYTE + i_need DSKSTCALL,BYTE + i_need DSKSTST,WORD + i_need BCON,DWORD + i_need DSKCHRET,BYTE + i_need DSKSTCNT,WORD + i_need IDLEINT,BYTE + i_need CONSWAP,BYTE + i_need user_SS,WORD + i_need user_SP,WORD + i_need User_In_AX,WORD + i_need ERRORMODE,BYTE + i_need ConC_spsave,WORD + i_need Exit_type,BYTE + i_need PFLAG,BYTE + i_need ExitHold,DWORD + i_need WPErr,BYTE + i_need ReadOp,BYTE + i_need CONTSTK,WORD + i_need Exit_Code,WORD + i_need CurrentPDB,WORD + i_need DIVMES,BYTE + i_need DivMesLen,WORD + i_need ALLOWED,BYTE + i_need FAILERR,BYTE + i_need EXTERR,WORD + i_need ERR_TABLE_24,BYTE + I_need ErrMap24,BYTE + I_need ErrMap24End,BYTE + I_need fAborting,BYTE + I_need AUXStack,BYTE + I_need SCAN_FLAG,BYTE + I_need EXTOPEN_ON,BYTE ;AN000; DOS 4.0 + I_need InterCon,BYTE ;AN000; DOS 4.0 + I_need DOS34_FLAG,WORD ;AN000; DOS 4.0 + I_need ACT_PAGE,WORD ;AN000; DOS 4.0 + I_need Special_Version,WORD ;AN007; DOS 4.0 +if debug + I_need BugLev,WORD + I_need BugTyp,WORD +include bugtyp.asm +endif +IF BUFFERFLAG + extrn restore_user_map:near +ENDIF + +Break + +ASSUME DS:NOTHING,ES:NOTHING + + procedure DSKSTATCHK,NEAR ; Check for ^C if only one level in + CMP BYTE PTR [INDOS],1 + retnz ; Do NOTHING + PUSH CX + PUSH ES + PUSH BX + PUSH DS + PUSH SI + PUSH CS + POP ES + Context DS + DOSAssume CS,,"DskStatChk" + MOV BYTE PTR [DSKSTCOM],DEVRDND + MOV BYTE PTR [DSKSTCALL],DRDNDHL + MOV [DSKSTST],0 + IF DBCS ;AN000; + MOV AL, [InterCon] ;AN000;get type of status read 2/13/KK + MOV BYTE PTR [DSKCHRET],AL ;AN000; load interim flag into packet + ENDIF ;AN000; + MOV BX,OFFSET DOSGROUP:DSKSTCALL + LDS SI,[BCON] +ASSUME DS:NOTHING + invoke DEVIOCALL2 + TEST [DSKSTST],STBUI + JZ GotCh ; No characters available + XOR AL,AL ; Set zero +RET36: + POP SI + POP DS + POP BX + POP ES + POP CX + return + +GotCh: + MOV AL,BYTE PTR [DSKCHRET] +DSK1: + CMP AL,"C"-"@" + JNZ RET36 + MOV BYTE PTR [DSKSTCOM],DEVRD + MOV BYTE PTR [DSKSTCALL],DRDWRHL + MOV BYTE PTR [DSKCHRET],CL + MOV [DSKSTST],0 + MOV [DSKSTCNT],1 + invoke DEVIOCALL2 ; Eat the ^C + POP SI + POP DS + POP BX ; Clean stack + POP ES + POP CX + JMP CNTCHAND + +NOSTOP: + CMP AL,"P"-"@" + JNZ check_next + CMP BYTE PTR [SCAN_FLAG],0 ; ALT_Q ? + JZ INCHKJ ; no + return +check_next: + IF NOT TOGLPRN + CMP AL,"N"-"@" + JZ INCHKJ + ENDIF + + CMP AL,"C"-"@" + JZ INCHKJ +check_end: + return + +INCHKJ: + JMP INCHK + +EndProc DSKSTATCHK + +; +; SpoolInt - signal processes that the DOS is truly idle. We are allowed to +; do this ONLY if we are working on a 1-12 system call AND if we are not in +; the middle of an INT 24. +; +procedure SPOOLINT,NEAR + PUSHF + test IdleInt,-1 + jz POPFRet + test ErrorMode,-1 + jnz POPFRet +; +; Note that we are going to allow an external program to issue system calls +; at this time. We MUST preserve IdleInt across this. +; + PUSH WORD PTR IdleInt + INT int_spooler + POP WORD PTR IdleInt +POPFRET: + POPF + return +EndProc SPOOLINT + + procedure STATCHK,NEAR + + invoke DSKSTATCHK ; Allows ^C to be detected under + ; input redirection + PUSH BX + XOR BX,BX + invoke GET_IO_SFT + POP BX + retc + MOV AH,1 + invoke IOFUNC + JZ SPOOLINT + CMP AL,"S"-"@" + JNZ NOSTOP + + CMP BYTE PTR [SCAN_FLAG],0 ;AN000; ALT_R ? + JNZ check_end ;AN000; yes + XOR AH,AH + invoke IOFUNC ; Eat Cntrl-S + JMP SHORT PAUSOSTRT +PRINTOFF: +PRINTON: + NOT BYTE PTR [PFLAG] + PUSH BX + MOV BX,4 + invoke GET_IO_SFT + POP BX + retc + PUSH ES + PUSH DI + PUSH DS + POP ES + MOV DI,SI ; ES:DI -> SFT + TEST ES:[DI.sf_flags],sf_net_spool + JZ NORM_PR ; Not redirected, echo is OK + Callinstall NetSpoolEchoCheck,MultNet,38,, ; See if allowed + JNC NORM_PR ; Echo is OK + MOV BYTE PTR [PFLAG],0 ; If not allowed, disable echo + Callinstall NetSpoolClose,MultNet,36,, ; and close + JMP SHORT RETP6 + +NORM_PR: + CMP BYTE PTR [PFLAG],0 + JNZ PRNOPN + invoke DEV_CLOSE_SFT + JMP SHORT RETP6 + +PRNOPN: + invoke DEV_OPEN_SFT +RETP6: + POP DI + POP ES + return + +PAUSOLP: + CALL SPOOLINT +PAUSOSTRT: + MOV AH,1 + invoke IOFUNC + JZ PAUSOLP +INCHK: + PUSH BX + XOR BX,BX + invoke GET_IO_SFT + POP BX + retc + XOR AH,AH + invoke IOFUNC + CMP AL,"P"-"@" +;;;;; 7/14/86 ALT_Q key fix + + JZ PRINTON ; no! must be CTRL_P + +NOPRINT: +;;;;; 7/14/86 ALT_Q key fix + IF NOT TOGLPRN + CMP AL,"N"-"@" + JZ PRINTOFF + ENDIF + CMP AL,"C"-"@" + retnz +EndProc STATCHK + + procedure CNTCHAND,NEAR +; Ctrl-C handler. +; "^C" and CR/LF is printed. Then the user registers are restored and the +; user CTRL-C handler is executed. At this point the top of the stack has 1) +; the interrupt return address should the user CTRL-C handler wish to allow +; processing to continue; 2) the original interrupt return address to the code +; that performed the function call in the first place. If the user CTRL-C +; handler wishes to continue, it must leave all registers unchanged and RET +; (not IRET) with carry CLEAR. If carry is SET then an terminate system call +; is simulated. + TEST [DOS34_FLAG],CTRL_BREAK_FLAG ;AN002; from RAWOUT + JNZ around_deadlock ;AN002; + MOV AL,3 ; Display "^C" + invoke BUFOUT + invoke CRLF +around_deadlock: ;AN002; + Context DS + CMP BYTE PTR [CONSWAP],0 + JZ NOSWAP + invoke SWAPBACK +NOSWAP: + CLI ; Prepare to play with stack + MOV SS,[user_SS] ; User stack now restored +ASSUME SS:NOTHING + MOV SP,[user_SP] + invoke restore_world ; User registers now restored +ASSUME DS:NOTHING + MOV BYTE PTR [INDOS],0 ; Go to known state + MOV BYTE PTR [ERRORMODE],0 + MOV [ConC_spsave],SP ; save his SP + CLC + INT int_ctrl_c ; Execute user Ctrl-C handler +; +; The user has returned to us. The circumstances we allow are: +; +; IRET We retry the operation by redispatching the system call +; CLC/RETF POP the stack and retry +; ... Exit the current process with ^C exit +; +; User's may RETURN to us and leave interrupts on. Turn 'em off just to be +; sure +; + CLI + MOV [user_IN_AX],ax ; save the AX + PUSHF ; and the flags (maybe new call) + POP AX +; +; See if the input stack is identical to the output stack +; + CMP SP,[ConC_spsave] + JNZ ctrlc_try_new ; current SP not the same as saved SP +; +; Repeat the operation by redispatching the system call. +; +ctrlc_repeat: + MOV AX,User_In_AX + transfer COMMAND +; +; The current SP is NOT the same as the input SP. Presume that he RETF'd +; leaving some flags on the stack and examine the input +; +ctrlc_try_new: + ADD SP,2 ; pop those flags + TEST AX,f_carry ; did he return with carry? + JZ Ctrlc_Repeat ; no carry set, just retry +; +; Well... time to abort the user. Signal a ^C exit and use the EXIT system +; call.. +; +ctrlc_abort: + MOV AX,(EXIT SHL 8) + 0 + MOV DidCTRLC,-1 + transfer COMMAND ; give up by faking $EXIT + +EndProc CNTCHAND + +Break + +; Default handler for division overflow trap + procedure DIVOV,NEAR +ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + MOV SI,OFFSET DOSGROUP:DIVMES + MOV BX,DivMesLen + MOV AX,CS + MOV SS,AX + MOV SP,OFFSET DOSGROUP:AUXSTACK ; Enough stack for interrupts + CALL OutMes + JMP ctrlc_abort ; Use Ctrl-C abort on divide overflow +EndProc DIVOV + +; +; OutMes: perform message output +; Inputs: SS:SI points to message +; BX has message length +; Outputs: message to BCON +; +procedure OutMes,NEAR + + Context ES ; get ES addressability + Context DS ; get DS addressability + + MOV BYTE PTR [DskStCom],DevWrt + MOV BYTE PTR [DskStCall],DRdWrHL + MOV [DskSTST],0 + MOV [DskStCnt],BX + MOV BX,OFFSET DOSGROUP:DskStCall + MOV WORD PTR [DskChRet+1],SI ; transfer address (need an EQU) + LDS SI,[BCON] +ASSUME DS:NOTHING + invoke DEVIOCALL2 + MOV WORD PTR [DskChRet+1],OFFSET DOSGROUP:DevIOBuf + MOV [DskStCnt],1 + return +EndProc OutMes + +Break + + procedure CHARHARD,NEAR +ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGROUP + +; Character device error handler +; Same function as HARDERR + + OR AH,allowed_FAIL + allowed_IGNORE + allowed_RETRY + MOV Allowed,AH + MOV WORD PTR [EXITHOLD+2],ES + MOV WORD PTR [EXITHOLD],BP + PUSH SI + AND DI,STECODE + MOV BP,DS ; Device pointer is BP:SI + CALL FATALC + POP SI + return +EndProc CHARHARD + +; Hard disk error handler. Entry conditions: +; DS:BX = Original disk transfer address +; DX = Original logical sector number +; CX = Number of sectors to go (first one gave the error) +; AX = Hardware error code +; DI = Original sector transfer count +; ES:BP = Base of drive parameters +; [READOP] = 0 for read, 1 for write +; [ALLOWED] Set with allowed responses to this error (other bits MUST BE 0) +; Output: +; [FAILERR] will be set if user responded FAIL + + procedure HardErr,NEAR + ASSUME DS:NOTHING,ES:NOTHING + + XCHG AX,DI ; Error code in DI, count in AX + AND DI,STECODE ; And off status bits + CMP DI,error_I24_write_protect ; Write Protect Error? + JNZ NOSETWRPERR + PUSH AX + MOV AL,ES:[BP.dpb_drive] + MOV BYTE PTR [WPERR],AL ; Flag drive with WP error + POP AX +NOSETWRPERR: + SUB AX,CX ; Number of sectors successfully transferred + ADD DX,AX ; First sector number to retry + PUSH DX + MUL ES:[BP.dpb_sector_size] ; Number of bytes transferred + POP DX + ADD BX,AX ; First address for retry + XOR AH,AH ; Flag disk section in error + CMP DX,ES:[BP.dpb_first_FAT] ; In reserved area? + JB ERRINT + INC AH ; Flag for FAT + CMP DX,ES:[BP.dpb_dir_sector] ; In FAT? + JAE TESTDIR ; No + MOV ES:[BP.dpb_free_cnt],-1 ; Err in FAT must force recomp of freespace + JMP SHORT ERRINT + +TESTDIR: + INC AH + CMP DX,ES:[BP.dpb_first_sector] ; In directory? + JB ERRINT + INC AH ; Must be in data area +ERRINT: + SHL AH,1 ; Make room for read/write bit + OR AH,BYTE PTR [READOP] ; Set bit 0 +; If we have a write protect error when writing on a critical area on disk, +; do not allow a retry as this may write out garbage on any subsequent disk. + ;test ah,1 + ;jz Not_Crit + ;cmp ah,5 + ;ja Not_Crit + ;and [ALLOWED],NOT Allowed_RETRY +Not_Crit: + OR AH,[ALLOWED] ; Set the allowed_ bits + entry FATAL + MOV AL,ES:[BP.dpb_drive] ; Get drive number + entry FATAL1 + MOV WORD PTR [EXITHOLD+2],ES + MOV WORD PTR [EXITHOLD],BP ; The only things we preserve + LES SI,ES:[BP.dpb_driver_addr] + MOV BP,ES ; BP:SI points to the device involved +; +; DI has the INT-24-style extended error. We now map the error code for this +; into the normalized get extended error set by using the ErrMap24 table as an +; translate table. Note that we translate ONLY the device returned codes and +; leave all others beyond the look up table alone. +; +FATALC: + call SET_I24_EXTENDED_ERROR + CMP DI,error_I24_gen_failure + JBE GOT_RIGHT_CODE ; Error codes above gen_failure get + MOV DI,error_I24_gen_failure ; mapped to gen_failure. Real codes + ; Only come via GetExtendedError + + entry NET_I24_ENTRY +; Entry point used by REDIRector on Network I 24 errors. +; +; ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGROUP +; +; ALL I 24 regs set up. ALL Extended error info SET. ALLOWED Set. +; EXITHOLD set for restore of ES:BP. + +GOT_RIGHT_CODE: + CMP BYTE PTR [ERRORMODE],0 ; No INT 24s if already INT 24 + JZ NoSetFail + MOV AL,3 + JMP FailRet +NoSetFail: +IF BUFFERFLAG + invoke RESTORE_USER_MAP ;AN000;LB. restore user's EMS map +ENDIF + MOV [CONTSTK],SP + Context ES + fmt TypINT24,LevLog,<"INT 24: AX = $x DI = $x\n">, +; +; Wango!!! We may need to free some user state info... In particular, we +; may have locked down a JFN for a user and he may NEVER return to us. Thus, +; we need to free it here and then reallocate it when we come back. +; + CMP SFN,-1 + JZ NoFree + SaveReg + LDS SI,pJFN + MOV BYTE PTR [SI],0FFH + RestoreReg +NoFree: + CLI ; Prepare to play with stack + INC BYTE PTR [ERRORMODE] ; Flag INT 24 in progress + DEC BYTE PTR [INDOS] ; INT 24 handler might not return +;; Extneded Open hooks + TEST [DOS34_FLAG],Force_I24_Fail ;AN000;IFS. form IFS Call Back ;AN000; + JNZ faili24 ;AN000;IFS. ;AN000; + TEST [EXTOPEN_ON],EXT_OPEN_I24_OFF ;AN000;IFS.I24 error disabled ;AN000; + JZ i24yes ;AN000;IFS.no ;AN000; +faili24: ;AN000; + MOV AL,3 ;AN000;IFS.fake fail ;AN000; + JMP passi24 ;AN000;IFS.exit ;AN000; +i24yes: ;AN000; + +;; Extended Open hooks + MOV SS,[user_SS] +ASSUME SS:NOTHING + MOV SP,ES:[user_SP] ; User stack pointer restored + INT int_fatal_abort ; Fatal error interrupt vector, must preserve ES + MOV ES:[user_SP],SP ; restore our stack + MOV ES:[user_SS],SS + MOV BP,ES + MOV SS,BP +ASSUME SS:DOSGROUP +passi24: ;AN000; + MOV SP,[CONTSTK] + INC BYTE PTR [INDOS] ; Back in the DOS + MOV BYTE PTR [ERRORMODE],0 ; Back from INT 24 + STI +;; MOV [ACT_PAGE],-1 ;LB. invalidate DOS active page ;AN000; +;; invoke SAVE_MAP ;LB. save user's EMS map ;AN000; + fmt TypINT24,LevLog,<"INT 24: User reply = $x\n">, +FAILRET: + LES BP,[EXITHOLD] +ASSUME ES:NOTHING +; +; Triage the user's reply. +; + CMP AL,1 + JB CheckIgnore ; 0 => ignore + JZ CheckRetry ; 1 => retry + CMP AL,3 ; 3 => fail + JNZ DoAbort ; 2, invalid => abort +; +; The reply was fail. See if we are allowed to fail. +; + TEST [ALLOWED],allowed_FAIL ; Can we? + JZ DoAbort ; No, do abort +DoFail: + MOV AL,3 ; just in case... + TEST [EXTOPEN_ON],EXT_OPEN_I24_OFF ;AN000;EO. I24 error disabled + JNZ cleanup ;AN000;EO. no + INC [FAILERR] ; Tell everybody +CleanUp: + MOV WpErr,-1 + CMP SFN,-1 + retz + SaveReg + MOV AX,SFN + LDS SI,pJFN + MOV [SI],AL + RestoreReg + return +; +; The reply was IGNORE. See if we are allowed to ignore. +; +CheckIgnore: + TEST [ALLOWED],allowed_IGNORE ; Can we? + JZ DoFail ; No, do fail + JMP CleanUp +; +; The reply was RETRY. See if we are allowed to retry. +; +CheckRetry: + TEST [ALLOWED],allowed_RETRY ; Can we? + JZ DoFail ; No, do fail + JMP CleanUp +; +; The reply was ABORT. +; +DoAbort: + Context DS + CMP BYTE PTR [CONSWAP],0 + JZ NOSWAP2 + invoke SWAPBACK +NOSWAP2: +; +; See if we are to truly abort. If we are in the process of aborting, turn +; this abort into a fail. +; + TEST fAborting,-1 + JNZ DoFail +; +; Set return code +; + MOV BYTE PTR [exit_Type],Exit_hard_error + XOR AL,AL +; +; we are truly aborting the process. Go restore information from the PDB as +; necessary. +; + Transfer exit_inner +; +; reset_environment checks the DS value against the CurrentPDB. If they are +; different, then an old-style return is performed. If they are the same, +; then we release jfns and restore to parent. We still use the PDB at DS:0 as +; the source of the terminate addresses. +; +; Some subtlety: We are about to issue a bunch of calls that *may* generate +; INT 24s. We *cannot* allow the user to restart the abort process; we may +; end up aborting the wrong process or turn a terminate/stay/resident into a +; normal abort and leave interrupt handlers around. What we do is to set a +; flag that will indicate that if any abort code is seen, we just continue the +; operation. In essence, we dis-allow the abort response. +; +; output: none. +; + entry reset_environment + ASSUME DS:NOTHING,ES:NOTHING + + invoke Reset_Version ;AN007;MS. reset version number + PUSH DS ; save PDB of process + +; +; There are no critical sections in force. Although we may enter here with +; critical sections locked down, they are no longer relevant. We may safely +; free all allocated resources. +; + MOV AH,82h + INT int_IBM + + MOV fAborting,-1 ; signal abort in progress + + CallInstall NetResetEnvironment, multNet, 34 ;DOS 4.00 doesn't need it + ; Allow REDIR to clear some stuff + ; On process exit. + MOV AL,int_Terminate + invoke $Get_interrupt_vector ; and who to go to + + POP CX ; get ThisPDB + SaveReg ; save return address + + MOV BX,[CurrentPDB] ; get currentPDB + MOV DS,BX + MOV AX,DS:[PDB_Parent_PID] ; get parentPDB + +; +; AX = parentPDB, BX = CurrentPDB, CX = ThisPDB +; Only free handles if AX <> BX and BX = CX and [exit_code].upper is not +; Exit_keep_process +; + CMP AX,BX + JZ reset_return ; parentPDB = CurrentPDB + CMP BX,CX + JNZ reset_return ; CurrentPDB <> ThisPDB + PUSH AX ; save parent + CMP BYTE PTR [exit_type],Exit_keep_process + JZ reset_to_parent ; keeping this process +; +; We are truly removing a process. Free all allocation blocks belonging to +; this PDB +; + invoke arena_free_process +; +; Kill off remainder of this process. Close file handles and signal to +; relevant network folks that this process is dead. Remember that CurrentPDB +; is STILL the current process! +; + invoke DOS_ABORT + +reset_to_parent: + POP [CurrentPDB] ; set up process as parent + +reset_return: ; come here for normal return + PUSH CS + POP DS + ASSUME DS:DOSGROUP + MOV AL,-1 +; +; make sure that everything is clean In this case ignore any errors, we cannot +; "FAIL" the abort, the program being aborted is dead. +; + EnterCrit critDisk + invoke FLUSHBUF + LeaveCrit critDisk +; +; Decrement open ref. count if we had done a virtual open earlier. +; + invoke CHECK_VIRT_OPEN +IF BUFFERFLAG + invoke RESTORE_USER_MAP ;AN000;LB. restore user's EMS map +ENDIF + CLI + MOV BYTE PTR [INDOS],0 ; Go to known state + MOV BYTE PTR [WPERR],-1 ; Forget about WP error + MOV fAborting,0 ; let aborts occur + POP WORD PTR ExitHold + POP WORD PTR ExitHold+2 +; +; Snake into multitasking... Get stack from CurrentPDB person +; + MOV DS,[CurrentPDB] + ASSUME DS:NOTHING + MOV SS,WORD PTR DS:[PDB_user_stack+2] + MOV SP,WORD PTR DS:[PDB_user_stack] + + ASSUME SS:NOTHING + invoke restore_world + ASSUME ES:NOTHING + MOV User_SP,AX + POP AX ; suck off CS:IP of interrupt... + POP AX + POP AX + MOV AX,0F202h ; STI + PUSH AX + PUSH WORD PTR [EXITHOLD+2] + PUSH WORD PTR [EXITHOLD] + MOV AX,User_SP + IRET ; Long return back to user terminate address +EndProc HardErr + +; +; This routine handles extended error codes. +; Input : DI = error code from device +; Output: All EXTERR fields are set +; +Procedure SET_I24_EXTENDED_ERROR,NEAR + PUSH AX + MOV AX,OFFSET DOSGroup:ErrMap24End + SUB AX,OFFSET DOSGroup:ErrMap24 +; +; AX is the index of the first unavailable error. Do not translate if +; greater or equal to AX. +; + CMP DI,AX + MOV AX,DI + JAE NoTrans + MOV AL,ErrMap24[DI] + XOR AH,AH +NoTrans: + MOV [EXTERR],AX + POP AX +; +; Now Extended error is set correctly. Translate it to get correct error +; locus class and recommended action. +; + PUSH SI + MOV SI,OFFSET DOSGROUP:ERR_TABLE_24 + invoke CAL_LK ; Set other extended error fields + POP SI + ret +EndProc SET_I24_EXTENDED_ERROR + +CODE ENDS + END + \ No newline at end of file diff --git a/v4.0/src/DOS/DELETE.ASM b/v4.0/src/DOS/DELETE.ASM new file mode 100644 index 0000000..c5473c0 --- /dev/null +++ b/v4.0/src/DOS/DELETE.ASM @@ -0,0 +1,777 @@ +; SCCSID = @(#)delete.asm 1.3 85/10/18 +; SCCSID = @(#)delete.asm 1.3 85/10/18 +TITLE DOS_DELETE - Internal DELETE call for MS-DOS +NAME DOS_DELETE +; Low level routine for deleting files +; +; DOS_DELETE +; REN_DEL_Check +; FastOpen_Delete ; DOS 3.3 +; FastOpen_Update ; DOS 3.3 +; FastSeek_Open ; DOS 4.00 +; FSeek_dispatch ; DOS 4.00 +; FastSeek_Close ; DOS 4.00 +; FastSeek_Delete ; DOS 4.00 +; Delete_FSeek ; DOS 4.00 +; FastSeek_Lookup ; DOS 4.00 +; FastSeek_Insert ; DOS 4.00 +; FastSeek_Truncate ; DOS 4.00 +; FS_doit ; DOS 4.00 +; +; Revision history: +; +; A000 version 4.00 Jan. 1988 +; + +; +; get the appropriate segment definitions +; +.xlist +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +INCLUDE FASTOPEN.INC +INCLUDE fastseek.inc +INCLUDE fastxxxx.inc +.cref +.list + +Installed = TRUE + + i_need NoSetDir,BYTE + i_need Creating,BYTE + i_need DELALL,BYTE + i_need THISDPB,DWORD + i_need THISSFT,DWORD + i_need THISCDS,DWORD + i_need CURBUF,DWORD + i_need ATTRIB,BYTE + i_need SATTRIB,BYTE + i_need WFP_START,WORD + i_need FoundDel,BYTE + i_need AUXSTACK,BYTE + i_need VOLCHNG_FLAG,BYTE + i_need JShare,DWORD + i_need FastOpenTable,BYTE ; DOS 3.3 + i_need FastTable,BYTE ; DOS 4.00 + i_need FSeek_drive,BYTE ; DOS 4.00 + i_need FSeek_firclus,WORD ; DOS 4.00 + i_need FSeek_logclus,WORD ; DOS 4.00 + i_need FSeek_logsave,WORD ; DOS 4.00 + i_need FastSeekflg,BYTE ; DOS 4.00 + i_need Del_ExtCluster,WORD ; DOS 4.00 + i_need SAVE_BX,WORD ; DOS 4.00 + i_need DMAADD,DWORD + i_need RENAMEDMA,BYTE + +; Inputs: +; [WFP_START] Points to WFP string ("d:/" must be first 3 chars, NUL +; terminated) +; [CURR_DIR_END] Points to end of Current dir part of string +; ( = -1 if current dir not involved, else +; Points to first char after last "/" of current dir part) +; [THISCDS] Points to CDS being used +; (Low word = -1 if NUL CDS (Net direct request)) +; [SATTRIB] Is attribute of search, determines what files can be found +; Function: +; Delete the specified file(s) +; Outputs: +; CARRY CLEAR +; OK +; CARRY SET +; AX is error code +; error_file_not_found +; Last element of path not found +; error_path_not_found +; Bad path (not in curr dir part if present) +; error_bad_curr_dir +; Bad path in current directory part of path +; error_access_denied +; Attempt to delete device or directory +; ***error_sharing_violation*** +; Deny both access required, generates an INT 24. +; This error is NOT returned. The INT 24H is generated, +; and the file is ignored (not deleted). Delete will +; simply continue on looking for more files. +; Carry will NOT be set in this case. +; DS preserved, others destroyed + +fileFound = 01h +fileDeleted = 10h + + procedure DOS_DELETE,NEAR + DOSAssume CS,,"DOS_Delete" + ASSUME ES:NOTHING + + Invoke TestNet + JNC LOCAL_DELETE +; invoke OWN_SHARE2 ;IFS. IFS owns share ? ;AN000; +; JZ ifsshare ;IFS. yes ;AN000; +; PUSH WORD PTR [DMAADD+2] ;IFS. save DMAADD ;AN000; +; PUSH WORD PTR [DMAADD] ;IFS. ;AN000; +; CALL IFS_SEARCH_FIRST ;IFS. do search first ;AN000; +; JC nofiles ;IFS. file not existing ;AN000; +delete_next_file: ;IFS. ;AN000; +; CALL IFS_REN_DEL_CHECK ;IFS. do REN_DEL_CHECK ;AN000; +; JNC share_okok ;IFS. share ok ;AN000; +; MOV AX,error_sharing_violation ;IFS. share violation ;AN000; +; JMP SHORT nofiles ;IFS. ;AN000; +share_okok: +; MOV AX,(multNET SHL 8) OR 19 ;IFS. delete it now ;AN000; +;; INT 2FH ;IFS. ;AN000; +; JC nofiles ;IFS. error ;AN000; +; invoke DOS_SEARCH_NEXT ;IFS. get next entry ;AN000; +; JNC delete_next_file ;IFS. ;AN000; +; CLC ;IFS. no more files ;AN000; +nofiles: +; POP WORD PTR [DMAADD] ;IFS. retor DMAADD ;AN000; +; POP WORD PTR [DMAADD+2] ;IFS. ;AN000; +; ret ;IFS. return +ifsshare: + + +IF NOT Installed + transfer NET_DELETE +ELSE + MOV AX,(multNET SHL 8) OR 19 + INT 2FH + return +ENDIF + +LOCAL_DELETE: + MOV [FoundDel],00 ; No files found and no files deleted + EnterCrit critDisk + MOV WORD PTR [CREATING],0E500H ; Assume not del *.* + MOV SI,[WFP_START] +SKPNUL: + LODSB + OR AL,AL + JNZ SKPNUL ; go to end + SUB SI,4 ; Back over possible "*.*" + CMP WORD PTR [SI],("." SHL 8 OR "*") + JNZ TEST_QUEST + CMP BYTE PTR [SI+2],"*" + JZ CHECK_ATTS +TEST_QUEST: + SUB SI,9 ; Back over possible "????????.???" + XCHG DI,SI + context ES + MOV AX,"??" + MOV CX,4 ; four sets of "??" + REPE SCASW + JNZ NOT_ALL + XCHG DI,SI + LODSW + CMP AX,("?" SHL 8) OR "." + JNZ NOT_ALL + LODSW + CMP AX,"??" + JNZ NOT_ALL +CHECK_ATTS: + MOV AL,BYTE PTR [SATTRIB] + AND AL,attr_hidden+attr_system+attr_directory+attr_volume_id+attr_read_only + ; Look only at hidden bits + CMP AL,attr_hidden+attr_system+attr_directory+attr_volume_id+attr_read_only + ; All must be set + JNZ NOT_ALL + +; NOTE WARNING DANGER----- +; This DELALL stuff is not safe. It allows directories to be deleted. +; It should ONLY be used by FORMAT in the ROOT directory. +; + + MOV [DELALL],0 ; DEL *.* - flag deleting all +NOT_ALL: + MOV [NoSetDir],1 + invoke GetPathNoSet + ASSUME ES:NOTHING + JNC Del_found + JNZ bad_path + OR CL,CL + JZ bad_path +No_file: + MOV AX,error_file_not_found +ErrorReturn: + STC + LeaveCrit critDisk + return + +bad_path: + MOV AX,error_path_not_found + JMP ErrorReturn + +Del_found: + JNZ NOT_DIR ; Check for dir specified + CMP DelAll,0 ; DelAll = 0 allows delete of dir. + JZ Not_Dir +Del_access_err: + MOV AX,error_access_denied + JMP ErrorReturn + +NOT_DIR: + OR AH,AH ; Check if device name + JS Del_access_err ; Can't delete I/O devices +; +; Main delete loop. CURBUF+2:BX points to a matching directory entry. +; +DELFILE: + OR [FoundDel],fileFound ; file found, not deleted yet +; +; If we are deleting the Volume ID, then we set VOLUME_CHNG flag to make +; DOS issue a build BPB call the next time this drive is accessed. +; + PUSH DS + MOV AH,[DELALL] + LDS DI,[CURBUF] +ASSUME DS:NOTHING +;; Extended Attributes +; PUSH AX ;FT. save cluster of XA ;AN000; +; MOV AX,DS:[BX.dir_ExtCluster];FT. ;AN000; +; MOV [Del_ExtCluster],AX ;FT. ;AN000; +; POP AX ;FT, ;AN000; + +;; Extended Attributes + TEST [Attrib],attr_read_only ; are we deleting RO files too? + JNZ DoDelete ; yes + TEST DS:[BX.dir_attr],attr_read_only + JZ DoDelete ; not read only + POP DS + JMP SHORT DelNxt ; Skip it (Note ES:BP not set) + +DoDelete: + call REN_DEL_Check ; Sets ES:BP = [THISDPB] + JNC DEL_SHARE_OK + POP DS + JMP SHORT DelNxt ; Skip it + +DEL_SHARE_OK: + Assert ISBUF,,"Del_Share_OK" + TEST [DI.buf_flags],buf_dirty ;LB. if already dirty ;AN000; + JNZ yesdirty ;LB. don't increment dirty count ;AN000; + invoke INC_DIRTY_COUNT ;LB. ;AN000; + OR [DI.buf_flags],buf_dirty +yesdirty: + MOV [BX],AH ; Put in E5H or 0 + MOV BX,[SI] ; Get firclus pointer + POP DS + DOSAssume CS,,"Del_Share_OK" + OR [FoundDel],fileDeleted ; Deleted file + CMP BX,2 + JB DELEXT ; File has invalid FIRCLUS (too small) + CMP BX,ES:[BP.dpb_max_cluster] + JA DELEXT ; File has invalid FIRCLUS (too big) +;; FastSeek 10/27/86 + CALL Delete_FSeek ; delete the fastseek entry +;; FastSeek 10/27/86 + + invoke RELEASE ; Free file data + JC No_fileJ +; DOS 3.3 FastOpen + + CALL FastOpen_Delete ; delete the dir info in fastopen + + +; DOS 3.3 FastOpen +;; Extended Attributes +DELEXT: + +; MOV BX,[Del_ExtCluster] ;FT. delete XA cluster chain ;AN000; +; CMP BX,2 ;FT. ;AN000; +; JB DELNXT ;FT. XA has invalid cluster (too small) ;AN000; +; CMP BX,ES:[BP.dpb_max_cluster];FT. ;AN000; +; JA DELNXT ;FT. XA has invalid cluster (too big) ;AN000; +; invoke RELEASE ;FT. Free extended attrs cluster ;AN000; +; JC No_fileJ ;FT. ;AN000; + +;; Extended Attributes +DELNXT: + LES BP,[THISDPB] ; Possible to get here without this set + invoke GETENTRY ; Registers need to be reset + JC No_fileJ + invoke NEXTENT +if DEBUG + JC Flsh + JMP DelFile +flsh: +ELSE + JNC DELFILE +ENDIF + LES BP,[THISDPB] ; NEXTENT sets ES=DOSGROUP + MOV AL,ES:[BP.dpb_drive] + invoke FLUSHBUF + JC No_fileJ +; +; Now we need to test FoundDel for our flags. The cases to consider are: +; +; not found not deleted file not found +; not found deleted *** impossible *** +; found not deleted access denied (read-only) +; found deleted no error +; + TEST FoundDel,fileDeleted ; did we delete a file? + JZ DelError ; no, figure out what's wrong. +; We set VOLCHNG_FLAG to indicate that we have changed the volume label +; and to force the DOS to issue a media check. + TEST [Attrib],attr_volume_id + jz No_Set_Flag + PUSH AX + PUSH ES + PUSH DI + LES DI,[THISCDS] +ASSUME ES:NOTHING + MOV AH,BYTE PTR ES:[DI] ; Get drive + SUB AH,'A' ; Convert to 0-based + mov byte ptr [VOLCHNG_FLAG],AH + XOR BH,BH ;>32mb delte volume id from boot record ;AN000; + invoke Set_Media_ID ;>32mb set voulme id to boot record ;AN000; + invoke FATRead_CDS ; force media check + POP DI + POP ES + POP AX +No_Set_Flag: + LeaveCrit critDisk ; carry is clear + return +DelError: + TEST FoundDel,fileFound ; not deleted. Did we find file? + JNZ Del_access_errJ ; yes. Access denied +No_fileJ: + JMP No_file ; Nope +Del_Access_errJ: + JMP Del_access_err + +EndProc DOS_DELETE + +Break + +; Inputs: +; [THISDPB] set +; [CURBUF+2]:BX points to entry +; [CURBUF+2]:SI points to firclus field of entry +; [WFP_Start] points to name +; Function: +; Check for Exclusive access on given file. +; Used by RENAME, SET_FILE_INFO, and DELETE. +; Outputs: +; ES:BP = [THISDPB] +; NOTE: The WFP string pointed to by [WFP_Start] Will be Modified. The +; last element will be loaded from the directory entry. This is +; so the name given to the sharer doesn't have any meta chars in +; it. +; Carry set if sharing violation, INT 24H generated +; NOTE THAT AX IS NOT error_sharing_violation. +; This is because input AX is preserved. +; Caller must set the error if needed. +; Carry clear +; OK +; AX,DS,BX,SI,DI preserved + + procedure REN_DEL_Check,NEAR +ASSUME DS:NOTHING,ES:NOTHING + + PUSH DS + PUSH DI + PUSH AX + PUSH BX + PUSH SI ; Save CURBUF pointers + context ES +ASSUME ES:DOSGROUP + MOV DI,[WFP_START] ; ES:DI -> WFP + MOV SI,BX + MOV DS,WORD PTR [CURBUF+2] ; DS:SI -> entry (FCB style name) + MOV BX,DI ; Set backup limit for skipback + ADD BX,2 ; Skip over d: to point to leading '\' + invoke StrLen ; CX is length of ES:DI including NUL + DEC CX ; Don't include nul in count + ADD DI,CX ; Point to NUL at end of string + invoke SkipBack ; Back up one element + INC DI ; Point to start of last element + MOV [SAVE_BX],DI ;IFS. save for DOS_RENAME ;AN000; + invoke PackName ; Transfer name from entry to ASCIZ tail. + POP SI ; Get back entry pointers + POP BX + PUSH BX + PUSH SI ; Back on stack + context DS +ASSUME DS:DOSGROUP +; +; Close the file if possible by us. +; +if installed + Call JShare + 13 * 4 +else + Call ShCloseFile +endif + MOV WORD PTR [THISSFT+2],DS + MOV WORD PTR [THISSFT],OFFSET DOSGROUP:AUXSTACK - (SIZE sf_entry) + ; Scratch space + XOR AH,AH ; Indicate file to DOOPEN (high bit off) + invoke DOOPEN ; Fill in SFT for share check + LES DI,[THISSFT] + MOV ES:[DI.sf_mode],sharing_deny_both ; requires exclusive access + MOV ES:[DI.sf_ref_count],1 ; Pretend open + invoke ShareEnter + jc CheckDone + LES DI,[THISSFT] + MOV ES:[DI.sf_ref_count],0 ; Pretend closed and free + invoke SHAREEND ; Tell sharer we're done with THISSFT + CLC +CheckDone: + LES BP,[THISDPB] + POP SI + POP BX + POP AX + POP DI + POP DS + return + +EndProc REN_DEL_Check + +Break + +; Inputs: +; None +; Function: +; Call FastOpen to delete the dir info. +; Outputs: +; None +; +; + + procedure FastOpen_Delete,NEAR +ASSUME DS:NOTHING,ES:NOTHING + PUSHF ; save flag + PUSH SI ; save registers + PUSH BX + PUSH AX + + MOV SI,[WFP_Start] ; ds:si points to path name + MOV AL,FONC_delete ; al = 3 +fastinvoke: + MOV BX,OFFSET DOSGROUP:FastTable + 2 + CALL DWORD PTR [BX] ; call fastopen + + POP AX ; restore registers + POP BX + POP SI + POPF ; restore flag + return +EndProc FastOpen_Delete + + +Break + +; Inputs: +; DL drive number (A=0,B=1,,,) +; CX first cluster # +; AH 0 updates dir entry +; 1 updates CLUSNUM , BP = new CLUSNUM +; ES:DI directory entry +; Function: +; Call FastOpen to update the dir info. +; Outputs: +; None +; +; + + procedure FastOpen_Update,NEAR +ASSUME DS:NOTHING,ES:NOTHING + PUSHF ; save flag + PUSH SI + PUSH BX ; save regs + PUSH AX + + MOV AL,FONC_update ; al = 4 + JMP fastinvoke + +EndProc FastOpen_Update + +Break + +; Inputs: +; DL drive number (0=A,1=B,,,) +; CX first cluster # +; Function: +; Create a file extent cache entry +; Outputs: +; None +; +; + + procedure FastSeek_Open,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; + TEST [FastSeekflg],Fast_yes ; Fastseek installed ? ;AN000; + JZ fs_no11 ; no ;AN000; + PUSH SI ; save regs ;AN000; + PUSH AX ;AN000; + MOV AL,FSEC_open ; al = 11 ;AN000; +fseek_disp: ;AN000; + CALL FSeek_dispatch ; call fastseek ;AN000; + POP AX ; restore regs ;AN000; + POP SI ;AN000; +fs_no11: ;AN000; + return ; return ;AN000; +EndProc FastSeek_Open ;AN000; + +; Inputs: +; none +; Function: +; Call Fastseek +; Outputs: +; Output of Fastseek +; + + procedure FSeek_dispatch,NEAR +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; + MOV AH,FastSeek_ID ; fastseek ID = 1 ;AN000; + entry Fast_Dispatch ; future fastxxxx entry ;AN000; + PUSH AX ; save ax ;AN000; + MOV AL,AH ; al=fastseek ID ;AN000; + XOR AH,AH ; ;AN000; + DEC AX ; ;AN000; + SHL AX,1 ; times 4 to get entry offset ;AN000; + SHL AX,1 ;AN000; + ;AN000; + MOV SI,OFFSET DOSGROUP:FastTable + 2 ; index to the ;AN000; + ADD SI,AX ; fastxxxx entry ;AN000; + POP AX ; restore ax ;AN000; + CALL DWORD PTR CS:[SI] ; call fastseek ;AN000; + return +EndProc FSeek_dispatch + +Break + +; Inputs: +; DL drive number (0=A,1=B,,,) +; CX first cluster # +; Function: +; Close a file extent entry +; Outputs: +; None +; +; + + procedure FastSeek_Close,NEAR +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + + TEST [FastSeekflg],Fast_yes ; Fastseek installed ? ;AN000; + JZ fs_no2 ; no ;AN000; + PUSH SI ; save regs ;AN000; + PUSH AX ; ;AN000; + MOV AL,FSEC_close ; al = 12 ;AN000; + JMP fseek_disp ; call fastseek ;AN000; +EndProc FastSeek_Close ;AN000; + +Break + +; Inputs: +; DL drive number (0=A,1=B,,,) +; CX first cluster # +; Function: +; Delete a file extent entry +; Outputs: +; None +; +; + + procedure FastSeek_Delete,NEAR +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; + TEST [FastSeekflg],Fast_yes ; Fastseek installed ? ;AN000; + JZ fs_no2 ; no ;AN000; + PUSH SI ; save regs ;AN000; + PUSH AX ;AN000; + MOV AL,FSEC_delete ; al=13 ;AN000; + JMP fseek_disp ; call fastseek ;AN000; +EndProc FastSeek_Delete ;AN000; + ;AN000; +; Inputs: +; FastSeekflg= 0 , not installed +; 1 , installed +; BX= first cluster number +; ES:BP = addr of DPB +; Function: +; Delete a file extent entry +; Outputs: +; None +; + + procedure Delete_FSeek,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + TEST [FastSeekflg],Fast_yes ; Fastseek installed ? ;AN000; + JZ fs_no2 ; no ;AN000; + PUSH CX ; save regs ;AN000; + PUSH DX ;AN000; + MOV CX,BX ; first cluster # ;AN000; + MOV DL,ES:[BP.dpb_drive] ; drive # ;AN000; + CALL FastSeek_Delete ; call fastseek to delete an entry ;AN000; + POP DX ; restore regs ;AN000; + POP CX ;AN000; +fs_no2: ;AN000; + return ; exit ;AN000; +EndProc Delete_FSeek ;AN000; + +Break + +; Inputs: +; FSeek_drive : drive number (0=A,1=B,,,) +; FSeek_firclus: first cluster # +; FSeek_logclus: logical cluster # +; Function: +; Look up a physical cluster # +; Outputs: +; carry clear, DI = physical cluster #, FSeek_logsave=DI-1 +; carry set, +; partially found, DI=last physical cluster # +; FSeek_logsave=last logical cluster # + + procedure FastSeek_Lookup,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + + PUSH AX ; save ax ;AN000; + MOV AL,FSEC_lookup ; al = 14 ;AN000; + PUSH BX ; save bx ;AN000; + CALL FS_doit ; call fastseek ;AN000; + MOV [FSeek_logsave],BX ; save returned BX ;AN000; + POP BX ; restore bx ;AN000; + POP AX ; restore ax ;AN000; + return ;AN000; +EndProc FastSeek_Lookup ;AN000; + ;AN000; + +Break + +; Inputs: +; FSeek_drive : drive number (0=A,1=B,,,) +; FSeek_firclus: first cluster # +; FSeek_logclus: logical cluster # +; DI: physical cluster # to be inserted +; Function: +; insert a physical cluster # +; Outputs: +; none +; + + procedure FastSeek_Insert,NEAR +ASSUME DS:NOTHING,ES:NOTHING + + TEST [FastSeekflg],FS_insert ; insert mode set ? ;AN000; + JZ no_insert ; no ;AN000; + ;AN000; + PUSH AX ; save regs ;AN000; + PUSH BX ;AN000; + MOV AL,FSEC_insert ; al = 15 ;AN000; +FSentry: ;AN000; + CALL FS_doit ; call fastseek ;AN000; + POP BX ; restore regs ;AN000; + POP AX ;AN000; +no_insert: + return +EndProc FastSeek_insert + +Break + +; Inputs: +; FSeek_drive : drive number (0=A,1=B,,,) +; FSeek_firclus: first cluster # +; FSeek_logclus: logical cluster # +; Function: +; truncate physical cluster #s starting from FSeek_logclus +; Outputs: +; none +; + + procedure FastSeek_Truncate,NEAR +ASSUME DS:NOTHING,ES:NOTHING + ;AN000; + TEST [FastSeekflg],Fast_yes ; Fastseek installed ? ;AN000; + JZ fs_no ; no ;AN000; + PUSH AX ; save regs ;AN000; + PUSH BX ;AN000; + MOV AL,FSEC_truncate ; al = 16 ;AN000; + JMP FSentry ; call fastseek ;AN000; +fs_no: ;AN000; + return ;AN000; +EndProc FastSeek_Truncate ;AN000; + +; Inputs: +; FSeek_drive : drive number (0=A,1=B,,,) +; FSeek_firclus: first cluster # +; FSeek_logclus: logical cluster # +; Function: +; set up parameters and call fastseek +; Outputs: +; outputs of fastseek +; + procedure FS_doit,NEAR +ASSUME DS:NOTHING,ES:NOTHING + ;AN000; + PUSH CX ; save regs ;AN000; + PUSH DX ;AN000; + PUSH SI ;AN000; + MOV DL,[FSeek_drive] ; set drive # ;AN000; + MOV CX,[FSeek_firclus] ; set 1st cluster # ;AN000; + MOV BX,[FSeek_logclus] ; set logical cluster # ;AN000; + ;AN000; + CALL FSeek_dispatch ; call fastseek ;AN000; + ;AN000; + ; carry clear if found in DI ;AN000; + POP SI ; otherwise, carry set ;AN000; + ;AN000; + POP DX ; restore regs ;AN000; + POP CX ;AN000; + return ;AN000; +EndProc FS_doit ;AN000; + + +; Inputs: +; same as DOS_SEARCH_FIRST +; Function: +; do a IFS search first +; Outputs: +; same as DOS_SEARCH_FIRST +; + procedure IFS_SEARCH_FIRST,NEAR ;AN000; + DOSAssume CS,,"IFS_SEARCH_FIRST" ;AN000; + ASSUME ES:NOTHING ;AN000; + +; MOV WORD PTR [DMAADD+2],DS ;IFS. replace with scratch area ;AN000;;AN000; +; MOV WORD PTR [DMAADD],OFFSET DOSGROUP:RENAMEDMA ;IFS. ;AN000; +; invoke SET_THISDPB ;IFS. THISDPB set ;AN000; +; invoke DOS_SEARCH_FIRST ;IFS. search first ;AN000; +; return ;AN000; +EndProc IFS_SEARCH_FIRST ;AN000; + + +; Inputs: +; THISDPB set +; WFP_Start points to name +; Function: +; do a IFS REN_DEL_CHECK +; Outputs: +; same as REN_DEL_CHECK +; + procedure IFS_REN_DEL_CHECK,NEAR ;AN000; + DOSAssume CS,,"IFS_REN_DEL_CHECK" ;AN000; + ASSUME ES:NOTHING ;AN000; + +; MOV AX,WORD PTR [DMAADD+2] ;IFS. set up ;AN000;;AN000; +; MOV WORD PTR [CURBUF+2],AX ;IFS. curbuf+2 : bx -> dir entry ;AN000; +; MOV BX,WORD PTR [DMAADD] ;IFS. ;AN000; +; ADD BX,21 ;IFS. ;AN000; +; MOV SI,BX ;IFS. curbuf+2:si -> dir_first ;AN000; +; ADD SI,dir_first ;IFS. ;AN000; +; EnterCrit critDisk ;IFS. enter critical section ;AN000; +; CALL REN_DEL_Check ;IFS. share check ;AN000; +; LeaveCrit critDisk ;IFS. leave critical section ;AN000; +; return ;AN000; +EndProc IFS_REN_DEL_CHECK ;AN000; + +CODE ENDS + END diff --git a/v4.0/src/DOS/DEV.ASM b/v4.0/src/DOS/DEV.ASM new file mode 100644 index 0000000..20c3f74 --- /dev/null +++ b/v4.0/src/DOS/DEV.ASM @@ -0,0 +1,841 @@ +; SCCSID = @(#)dev.asm 1.2 85/07/23 +; SCCSID = @(#)dev.asm 1.2 85/07/23 +TITLE DEV - Device call routines +NAME Dev +; Misc Routines to do 1-12 low level I/O and call devices +; +; IOFUNC +; DEVIOCALL +; SETREAD +; SETWRITE +; DEVIOCALL2 +; DEV_OPEN_SFT +; DEV_CLOSE_SFT +; RW_SC +; IN_SC +; INVALIDATE_SC +; VIRREAD +; SC2BUF +; +; Revision history: +; +; A000 version 4.00 Jan. 1988 +; A010 disable change line for SHARE /NC + +; +; get the appropriate segment definitions +; +.xlist +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +include version.inc +.cref +.list + + i_need IOXAD,DWORD + i_need IOSCNT,WORD + i_need DEVIOBUF,4 + i_need IOCALL,BYTE + i_need IOMED,BYTE + i_need IORCHR,BYTE + i_need CALLSCNT,WORD + i_need DMAAdd,DWORD + i_need CallDevAd,DWORD + i_need CallXAD,DWORD + i_need DPBHead,DWORD + i_need ThisSFT,DWORD + i_need ThisDPB,DWORD + i_need DevCall,DWORD + i_need VerFlg,BYTE + i_need HIGH_SECTOR,WORD ;AN000; + i_need CALLSSEC,WORD ;AN000; + i_need CALLNEWSC,DWORD ;AN000; + i_need SC_CACHE_COUNT,WORD ;AN000; + i_need SC_CACHE_PTR,DWORD ;AN000; + i_need CURSC_SECTOR,WORD ;AN000; + i_need SEQ_SECTOR,DWORD ;AN000; + i_need SC_SECTOR_SIZE,WORD ;AN000; + i_need CURSC_DRIVE,BYTE ;AN000; + i_need SC_DRIVE,BYTE ;AN000; + i_need SC_STATUS,WORD ;AN000; + i_need SC_FLAG,BYTE ;AN000; + i_need TEMP_VAR,WORD ;AN000; + i_need TEMP_VAR2,WORD ;AN000; + i_need InterChar,BYTE ;AN000; interim character flag 2/13/KK + i_need InterCon,BYTE ;AN000; Console mode flag(1:interim mode) 2/13/KK + i_need SaveCurFlg,BYTE ;AN000; Console out mode(1:print & don't adv cursor) 2 /13/KK + i_need DDMOVE,BYTE ;AN000; flag for DWORD move + i_need DOS34_FLAG,WORD ;AN000; + i_need fshare,BYTE ;AN010; share flag + +Break + +; Inputs: +; DS:SI Points to SFT +; AH is function code +; = 0 Input +; = 1 Input Status +; = 2 Output +; = 3 Output Status +; = 4 Flush +; = 5 Input Status - System WAIT invoked for K09 if no char +; present. +; AL = character if output +; Function: +; Perform indicated I/O to device or file +; Outputs: +; AL is character if input +; If a status call +; zero set if not ready +; zero reset if ready (character in AL for input status) +; For regular files: +; Input Status +; Gets character but restores position +; Zero set on EOF +; Input +; Gets character advances position +; Returns ^Z on EOF +; Output Status +; Always ready +; AX altered, all other registers preserved + + procedure IOFUNC,NEAR +ASSUME DS:NOTHING,ES:NOTHING + + Assert ISSFT,,"IOFUNC" + MOV WORD PTR [IOXAD+2],SS + MOV WORD PTR [IOXAD],OFFSET DOSGROUP:DEVIOBUF + MOV WORD PTR [IOSCNT],1 + MOV WORD PTR [DEVIOBUF],AX + TEST [SI.sf_flags],sf_isnet + JZ IOTO22 ;AN000; + JMP IOTOFILE ;AN000; +IOTO22: + TEST [SI.sf_flags],devid_device + JNZ IOTo33 ;AN000; + JMP IOTOFILE ;AN000; +IOTO33: + invoke save_world + MOV DX,DS + MOV BX,SS + MOV DS,BX + MOV ES,BX + ASSUME DS:DOSGroup + XOR BX,BX + cmp ah,5 ; system wait enabled? + jnz no_sys_wait + or bx,0400H ; Set bit 10 in status word for driver + ; It is up to device driver to carry out + ; appropriate action. +no_sys_wait: + MOV [IOCALL.REQSTAT],BX + XOR BX,BX + MOV BYTE PTR [IOMED],BL + +Table Segment +Public DEV001S, DEV001E ; Pathgen labels +DEV001s: +; length of packets +LenTab DB DRDWRHL, DRDNDHL, DRDWRHL, DSTATHL, DFLSHL, DRDNDHL + +; Error Function + +CmdTab DB 86h, DEVRD ; 0 input + DB 86h, DEVRDND ; 1 input status + DB 87h, DEVWRT ; 2 output + DB 87h, DEVOST ; 3 output status + DB 86h, DEVIFL ; 4 input flush + DB 86H, DEVRDND ; 5 input status with system WAIT +DEV001E: +Table ENDS + + MOV BL,AH ; get function + MOV AH,LenTab[BX] + SHL BX,1 + MOV CX,WORD PTR CmdTab[BX] + + MOV BX,OFFSET DOSGROUP:IOCALL + + MOV [IOCALL.REQLEN],AH + MOV [IOCALL.REQFUNC],CH + IF DBCS ;AN000; +;----------------------------- Start of DBCS 2/13/KK + PUSH CX ;AN000; + MOV CL, [InterCon] ;AN000; + CMP CH, DEVRD ;AN000; 0 input + JZ SETIN ;AN000; + CMP CH, DEVRDND ;AN000; 1(5) input status without(with) system WAIT + JZ SETIN ;AN000; + MOV CL, [SaveCurflg] ;AN000; + CMP CH, DEVWRT ;AN000; 2 output + JZ CHKERROUT ;AN000; + XOR CL,CL ;AN000; else, do normal +SETIN: ;AN000; + MOV BYTE PTR [IoMed], CL ;AN000; set interim I/O indication + POP CX ;AN000; +;----------------------------- End of DBCS 2/13/KK + ENDIF ;AN000; + MOV DS,DX +ASSUME DS:NOTHING + CALL DEVIOCALL + MOV DI,[IOCALL.REQSTAT] + TEST DI,STERR + JNZ DevErr +OkDevIO: + MOV AX,SS + MOV DS,AX + ASSUME DS:DOSGroup + IF DBCS ;AN000; + MOV [InterChar],0 ;AN000; reset interim character flag 2/13/KK + TEST DI,Ddkey ;AN000; is this a dead key (interim char)? 2/13/KK + JZ NotInterim ;AN000; no, flag already reset... 2/13/KK + INC [InterChar] ;AN000; yes, set flag for future 2/13/KK +NotInterim: ;AN000; 2/13/KK + ENDIF ;AN000; + CMP CH,DEVRDND + JNZ DNODRD + MOV AL,BYTE PTR [IORCHR] + MOV [DEVIOBUF],AL + +DNODRD: MOV AH,BYTE PTR [IOCALL.REQSTAT+1] + NOT AH ; Zero = busy, not zero = ready + AND AH,STBUI SHR 8 + +QuickReturn: ;AN000; 2/13/KK + invoke restore_world +ASSUME DS:NOTHING + MOV AX,WORD PTR [DEVIOBUF] + return + +;IOTOFILEJ: +; JMP SHORT IOTOFILE + IF DBCS ;AN000; +;------------------------------ Start of DBCS 2/13/KK +CHKERROUT: ;AN000; + MOV DS, DX ;AN000; + TEST [SI.sf_flags], devid_device_con_out ;AN000; output to console ? + JNZ GOOD ;AN000; yes + CMP CL, 01 ;AN000; write interim ? + JNZ GOOD ;AN000; no, + POP CX ;AN000; + JMP SHORT QuickReturn ;AN000; avoid writting interims to other than + ;AN000; console device +GOOD: ;AN000; + PUSH SS ;AN000; + POP DS ;AN000; + JMP SETIN ;AN000; +;------------------------------ End of DBCS 2/13/KK + ENDIF ;AN000; +DevErr: + TEST CS:[DOS34_FLAG],X25_Special ;AN000; from disk.asm + JZ notx25 ;AN000; no + PUSH AX ;AN000; unknown command ? + MOV AX,DI ;AN000; + AND AX,error_I24_bad_command ;AN000; + CMP AL,error_I24_bad_command ;AN000; + POP AX ;AN000; + JNZ notx25 ;AN000; no, then error + JMP okDevIO ;AN000; +notx25: + MOV AH,CL + invoke CHARHARD + CMP AL,1 + JNZ NO_RETRY + invoke restore_world + JMP IOFUNC + +NO_RETRY: +; Know user must have wanted Ignore OR Fail. Make sure device shows ready +; so that DOS doesn't get caught in a status loop when user simply wants +; to ignore the error. + AND BYTE PTR [IOCALL.REQSTAT+1], NOT (STBUI SHR 8) + JMP OKDevIO + +IOTOFILE: +ASSUME DS:NOTHING + OR AH,AH + JZ IOIN + DEC AH + JZ IOIST + DEC AH + JZ IOUT + return ; NON ZERO FLAG FOR OUTPUT STATUS + +IOIST: + PUSH WORD PTR [SI.sf_position] ; Save position + PUSH WORD PTR [SI.sf_position+2] + CALL IOIN + POP WORD PTR [SI.sf_position+2] ; Restore position + POP WORD PTR [SI.sf_position] + return + +IOUT: + CALL SETXADDR + invoke DOS_WRITE + CALL RESTXADDR ; If you change this into a jmp don't + return ; come crying to me when things don't + ; work ARR + +IOIN: + CALL SETXADDR + OR [DOS34_FLAG],Disable_EOF_I24 ;AN000; + invoke DOS_READ + AND [DOS34_FLAG],NO_Disable_EOF_I24 ;AN000; + OR CX,CX ; Check EOF + CALL RESTXADDR + MOV AL,[DEVIOBUF] ; Get byte from trans addr + retnz + MOV AL,1AH ; ^Z if no bytes + return + +SETXADDR: + POP WORD PTR [CALLSCNT] ; Return address + invoke save_world + PUSH WORD PTR [DMAADD] ; Save Disk trans addr + PUSH WORD PTR [DMAADD+2] + MOV WORD PTR [THISSFT+2],DS + Context DS + MOV WORD PTR [THISSFT],SI ; Finish setting SFT pointer + MOV CX,WORD PTR [IOXAD+2] + MOV WORD PTR [DMAADD+2],CX + MOV CX,WORD PTR [IOXAD] + MOV WORD PTR [DMAADD],CX ; Set byte trans addr + MOV CX,[IOSCNT] ; ioscnt specifies length of buffer + JMP SHORT RESTRET ; RETURN ADDRESS + +RESTXADDR: + DOSAssume CS,,"RestXAddr" + POP WORD PTR [CALLSCNT] ; Return address + POP WORD PTR [DMAADD+2] ; Restore Disk trans addr + POP WORD PTR [DMAADD] + invoke restore_world +ASSUME DS:NOTHING +RESTRET:JMP WORD PTR [CALLSCNT] ; Return address +EndProc IOFUNC + +Break + +; Inputs: +; ES:DI Points to SFT +; Function: +; Issue an OPEN call to the correct device +; Outputs: +; None +; ALL preserved + + procedure DEV_OPEN_SFT,NEAR +ASSUME DS:NOTHING,ES:NOTHING + + Assert ISSFT,,"Dev_Open_SFT" + invoke Save_World + MOV AL,DEVOPN + JMP SHORT DO_OPCLS + +EndProc DEV_OPEN_SFT + +; Inputs: +; ES:DI Points to SFT +; Function: +; Issue a CLOSE call to the correct device +; Outputs: +; None +; ALL preserved + + procedure DEV_CLOSE_SFT,NEAR +ASSUME DS:NOTHING,ES:NOTHING + + Assert ISSFT,,"Dev_Close_SFT" + invoke Save_World + MOV AL,DEVCLS + +; +; Main entry for device open and close. AL contains the function requested. +; Subtlety: if Sharing is NOT loaded then we do NOT issue open/close to block +; devices. This allows networks to function but does NOT hang up with bogus +; change-line code. +; + entry DO_OPCLS +; +; Is the SFT for the net? If so, no action necessary. +; + invoke Test_IFS_Remote ;AC000; + JNZ OPCLS_DONE ; NOP on net SFTs + XOR AH,AH ; Unit + TEST ES:[DI.sf_flags],devid_device + LES DI,ES:[DI.sf_devptr] ; Get DPB or device + JNZ Got_Dev_Addr +; +; We are about to call device open/close on a block driver. If no sharing +; then just short circuit to done. +; +;;;;; invoke CheckShare + CMP fshare,1 ;AN010; /NC or no SHARE + JBE opCLs_Done ;AN010; yes + MOV AH,ES:[DI.dpb_UNIT] + MOV CL,ES:[DI.dpb_drive] + LES DI,ES:[DI.dpb_driver_addr] ; Get device +GOT_DEV_ADDR: ; ES:DI -> device + TEST ES:[DI.SDEVATT],DEVOPCL + JZ OPCLS_DONE ; Device can't + PUSH ES + POP DS + MOV SI,DI ; DS:SI -> device +OPCLS_RETRY: + Context ES + MOV DI,OFFSET DOSGROUP:DEVCALL + MOV BX,DI + PUSH AX + MOV AL,DOPCLHL + STOSB ; Length + POP AX + XCHG AH,AL + STOSB ; Unit + XCHG AH,AL + STOSB ; Command + MOV WORD PTR ES:[DI],0 ; Status + PUSH AX ; Save Unit,Command + invoke DEVIOCALL2 + MOV DI,ES:[BX.REQSTAT] + TEST DI,STERR + JZ OPCLS_DONEP ; No error + TEST [SI.SDEVATT],DEVTYP + JZ BLKDEV + MOV AH,86H ; Read error in data, Char dev + JMP SHORT HRDERR + +BLKDEV: + MOV AL,CL ; Drive # in AL + MOV AH,6 ; Read error in data, Blk dev +HRDERR: + invoke CHARHARD + CMP AL,1 + JNZ OPCLS_DONEP ; IGNORE or FAIL + ; Note that FAIL is essentually IGNORED + POP AX ; Get back Unit, Command + JMP OPCLS_RETRY + +OPCLS_DONEP: + POP AX ; Clean stack +OPCLS_DONE: + invoke Restore_World + return + +EndProc DEV_CLOSE_SFT + +Break + +; Inputs: +; DS:SI Points to device SFT +; ES:BX Points to request data +; Function: +; Call the device +; Outputs: +; DS:SI -> Device driver +; DS:SI,AX destroyed, others preserved + + procedure DEVIOCALL,NEAR +ASSUME DS:NOTHING,ES:NOTHING + + Assert ISSFT,,"DevIOCall" + LDS SI,[SI.sf_devptr] + + entry DEVIOCALL2 + + EnterCrit critDevice + + TEST [SI.SDEVATT],DevTyp ;AN000; >32mb block device ? + JNZ chardev2 ;AN000; >32mb no + CMP ES:[BX.REQFUNC],DEVRD ;AN000; >32mb read ? + JZ chkext ;AN000; >32mb yes + CMP ES:[BX.REQFUNC],DEVWRT ;AN000; >32mb write ? + JZ chkext ;AN000; >32mb yes + CMP ES:[BX.REQFUNC],DEVWRTV;AN000; >32mb write/verify ? + JNZ chardev2 ;AN000; >32mb no +chkext: + CALL RW_SC ;AN000;LB. use secondary cache if there + JC dev_exit ;AN000;LB. done + + TEST [SI.SDEVATT],EXTDRVR ;AN000;>32mb extended driver? + JZ chksector ;AN000;>32mb no + ADD BYTE PTR ES:[BX],8 ;AN000;>32mb make length to 30 + MOV AX,[CALLSSEC] ;AN000;>32mb + MOV [CALLSSEC],-1 ;AN000;>32mb old sector =-1 + MOV WORD PTR [CALLNEWSC],AX ;AN000;>32mb new sector = + MOV AX,[HIGH_SECTOR] ;AN000; >32mb low sector,high sector + MOV WORD PTR [CALLNEWSC+2],AX ;AN000; >32mb + JMP chardev2 ;AN000; >32mb +chksector: ;AN000; >32mb + CMP [HIGH_SECTOR],0 ;AN000; >32mb if >32mb + JZ chardev2 ;AN000; >32mb then fake error + MOV ES:[BX.REQSTAT],STERR+STDON+ERROR_I24_NOT_DOS_DISK ;AN000; >32mb + JMP SHORT dev_exit ;AN000; >32mb + +chardev2: ;AN000; +; As above only DS:SI points to device header on entry, and DS:SI is preserved + MOV AX,[SI.SDEVSTRAT] + MOV WORD PTR [CALLDEVAD],AX + MOV WORD PTR [CALLDEVAD+2],DS + CALL DWORD PTR [CALLDEVAD] + MOV AX,[SI.SDEVINT] + MOV WORD PTR [CALLDEVAD],AX + CALL DWORD PTR [CALLDEVAD] + CALL VIRREAD ;AN000;LB. move data from SC to buffer + JC chardev2 ;AN000;LB. bad sector or exceeds max sec +dev_exit: + LeaveCrit critDevice + return +EndProc DEVIOCALL + +Break + +; Inputs: +; DS:BX = Transfer Address +; CX = Record Count +; DX = Starting Record +; AH = Media Byte +; AL = Unit Code +; Function: +; Set up the device call header at DEVCALL +; Output: +; ES:BX Points to DEVCALL +; No other registers effected + + procedure SETREAD,NEAR +ASSUME DS:NOTHING,ES:NOTHING + + PUSH DI + PUSH CX + PUSH AX + MOV CL,DEVRD +SETCALLHEAD: + MOV AL,DRDWRHL + PUSH SS + POP ES + MOV DI,OFFSET DOSGROUP:DEVCALL + STOSB ; length + POP AX + STOSB ; Unit + PUSH AX + MOV AL,CL + STOSB ; Command code + XOR AX,AX + STOSW ; Status + ADD DI,8 ; Skip link fields + POP AX + XCHG AH,AL + STOSB ; Media byte + XCHG AL,AH + PUSH AX + MOV AX,BX + STOSW + MOV AX,DS + STOSW ; Transfer addr + POP CX ; Real AX + POP AX ; Real CX + STOSW ; Count + XCHG AX,DX ; AX=Real DX, DX=real CX, CX=real AX + STOSW ; Start + XCHG AX,CX + XCHG DX,CX + POP DI + MOV BX,OFFSET DOSGROUP:DEVCALL + return + + entry SETWRITE +ASSUME DS:NOTHING,ES:NOTHING + +; Inputs: +; DS:BX = Transfer Address +; CX = Record Count +; DX = Starting Record +; AH = Media Byte +; AL = Unit Code +; Function: +; Set up the device call header at DEVCALL +; Output: +; ES:BX Points to DEVCALL +; No other registers effected + + PUSH DI + PUSH CX + PUSH AX + MOV CL,DEVWRT + ADD CL,[VERFLG] + JMP SHORT SETCALLHEAD +EndProc SETREAD + + +Break + +; Inputs: +; [SC_CACHE_COUNT]= secondary cache count +; [SC_STATUS]= SC validity status +; [SEQ_SECTOR]= last sector read +; Function: +; Read from or write through secondary cache +; Output: +; ES:BX Points to DEVCALL +; carry clear, I/O is not done +; [SC_FLAG]=1 if continuos sectors will be read +; carry set, I/O is done + + + procedure RW_SC,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + + CMP [SC_CACHE_COUNT],0 ;AN000;LB. secondary cache exists? + JZ scexit4 ;AN000;LB. no, do nothing + CMP [CALLSCNT],1 ;AN000;LB. sector count = 1 (buffer I/O) + JNZ scexit4 ;AN000;LB. no, do nothing + PUSH CX ;AN000;;LB. + PUSH DX ;AN000;;LB. yes + PUSH DS ;AN000;;LB. save registers + PUSH SI ;AN000;;LB. + PUSH ES ;AN000;;LB. + PUSH DI ;AN000;;LB. + MOV DX,WORD PTR [CALLSSEC] ;AN000;;LB. starting sector + CMP BYTE PTR [DEVCALL.REQFUNC],DEVRD ;AN000;LB. read ? ;AN000; + JZ doread ;AN000;LB. yes ;AN000; + CALL INVALIDATE_SC ;AN000;LB. invalidate SC ;AN000; + JMP scexit2 ;AN000;LB. back to normal ;AN000; +scexit4: ;AN000; ;AN000; + CLC ;AN000;LB. I/O not done yet ;AN000; + return ;AN000;LB. ;AN000; +doread: ;AN000; ;AN000; + CALL SC2BUF ;AN000;LB. check if in SC ;AN000; + JC readSC ;AN000;LB. ;AN000; + MOV [DEVCALL.REQSTAT],STDON ;AN000;LB. fake done and ok ;AN000; + STC ;AN000;LB. set carry ;AN000; + JMP saveseq ;AN000;LB. save seq. sector # ;AN000; +readSC: ;AN000; + MOV AX,WORD PTR [HIGH_SECTOR] ;AN000;;LB. subtract sector num from + MOV CX,WORD PTR [CALLSSEC] ;AN000;;LB. saved sequential sector + SUB CX,WORD PTR [SEQ_SECTOR] ;AN000;;LB. number + SBB AX,WORD PTR [SEQ_SECTOR+2] ;AN000;;LB. + CMP AX,0 ;AN000;;LB. greater than 64K + JNZ saveseq2 ;AN000;;LB. yes,save seq. sector # +chklow: ;AN000; + CMP CX,1 ;AN000;;LB. <= 1 + JA saveseq2 ;AN000;;LB. no, not sequential + MOV [SC_STATUS],-1 ;AN000;;LB. prsume all SC valid + MOV AX,[SC_CACHE_COUNT] ;AN000;;LB. yes, sequential + MOV [CALLSCNT],AX ;AN000;;LB. read continuous sectors +readsr: + MOV AX,WORD PTR [CALLXAD+2] ;AN000;;LB. save buffer addr + MOV [TEMP_VAR2],AX ;AN000;;LB. in temp vars + MOV AX,WORD PTR [CALLXAD] ;AN000;;LB. + MOV [TEMP_VAR],AX ;AN000;;LB. + ;AN000; + MOV AX,WORD PTR [SC_CACHE_PTR] ;AN000;LB. use SC cache addr as ;AN000; + MOV WORD PTR [CALLXAD],AX ;AN000;LB. transfer addr ;AN000; + MOV AX,WORD PTR [SC_CACHE_PTR+2] ;AN000;LB. ;AN000; + MOV WORD PTR [CALLXAD+2],AX ;AN000;LB. ;AN000; + MOV [SC_FLAG],1 ;AN000;LB. flag it for later ;AN000; + MOV AL,[SC_DRIVE] ;AN000;;LB. current drive + MOV [CURSC_DRIVE],AL ;AN000;;LB. set current drive + MOV AX,WORD PTR [CALLSSEC] ;AN000;;LB. current sector + MOV [CURSC_SECTOR],AX ;AN000;;LB. set current sector + MOV AX,WORD PTR [CALLSSEC+2] ;AN000;;LB. + MOV [CURSC_SECTOR+2],AX ;AN000;;LB. +saveseq2: ;AN000; + CLC ;AN000;LB. clear carry ;AN000; +saveseq: ;AN000; ;AN000; + MOV AX,[HIGH_SECTOR] ;AN000;LB. save current sector # ;AN000; + MOV WORD PTR [SEQ_SECTOR+2],AX ;AN000;LB. for access mode ref. ;AN000; + MOV AX,[CALLSSEC] ;AN000;LB. ;AN000; + MOV WORD PTR [SEQ_SECTOR],AX ;AN000;LB. ;AN000; + JMP scexit ;AN000;LB. ;AN000; + ;AN000; +scexit2: ;AN000;LB. ;AN000; + CLC ;AN000;LB. clear carry ;AN000; +scexit: ;AN000; ;AN000; + POP DI ;AN000;;LB. + POP ES ;AN000;;LB. restore registers + POP SI ;AN000;;LB. + POP DS ;AN000;;LB. + POP DX ;AN000;;LB. + POP CX ;AN000;;LB. + return ;AN000;;LB. + ;AN000; +EndProc RW_SC ;AN000; + +Break + +; Inputs: [SC_DRIVE]= requesting drive +; [CURSC_DRIVE]= current SC drive +; [CURSC_SECTOR] = starting scetor # of SC +; [SC_CACHE_COUNT] = SC count +; [HIGH_SECTOR]:DX= sector number +; Function: +; Check if the sector is in secondary cache +; Output: +; carry clear, in SC +; CX= the index in the secondary cache +; carry set, not in SC +; + + procedure IN_SC,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + + MOV AL,[SC_DRIVE] ;AN000;;LB. current drive + CMP AL,[CURSC_DRIVE] ;AN000;;LB. same as SC drive + JNZ outrange2 ;AN000;;LB. no + MOV AX,WORD PTR [HIGH_SECTOR] ;AN000;;LB. subtract sector num from + MOV CX,DX ;AN000;;LB. secondary starting sector + SUB CX,WORD PTR [CURSC_SECTOR] ;AN000;;LB. number + SBB AX,WORD PTR [CURSC_SECTOR+2] ;AN000;;LB. + CMP AX,0 ;AN000;;LB. greater than 64K + JNZ outrange2 ;AN000;;LB. yes + CMP CX,[SC_CACHE_COUNT] ;AN000;;LB. greater than SC count + JAE outrange2 ;AN000;;LB. yes + CLC ;AN000;;LB. clear carry + JMP short inexit ;AN000;;LB. in SC +outrange2: ;AN000;;LB. set carry + STC ;AN000;;LB. +inexit: ;AN000;;LB. + return ;AN000;;LB. + +EndProc IN_SC ;AN000; + +Break + +; Inputs: [SC_DRIVE]= requesting drive +; [CURSC_DRIVE]= current SC drive +; [CURSC_SECTOR] = starting scetor # of SC +; [SC_CACHE_COUNT] = SC count +; [SC_STAUS] = SC status word +; [HIGH_SECTOR]:DX= sceotor number +; +; Function: +; invalidate secondary cache if in there +; Output: +; [SC_STATUS] is updated +; + + procedure INVALIDATE_SC,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + + CALL IN_SC ;AN000;;LB. in secondary cache + JC outrange ;AN000;;LB. no + MOV AX,1 ;AN000;;LB. invalidate the sector + SHL AX,CL ;AN000;;LB. in the secondary cache + NOT AX ;AN000;;LB. + AND [SC_STATUS],AX ;AN000;;LB. save the status +outrange: ;AN000;;LB. + return ;AN000;;LB. + +EndProc INVALIDATE_SC ;AN000; + + +Break + +; Inputs: SC_FLAG = 0 , no sectors were read into SC +; 1, continous sectors were read into SC +; Function: +; Move data from SC to buffer +; Output: +; carry clear, data is moved to buffer +; carry set, bad sector or exceeds maximum sector +; SC_FLAG =0 +; CALLSCNT=1 +; SC_STATUS= -1 if succeeded +; 0 if failed + + procedure VIRREAD,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + + CMP [SC_FLAG],0 ;AN000;;LB. from SC fill + JZ sc2end ;AN000;;LB. no + MOV AX,[TEMP_VAR2] ;AN000;;LB. restore buffer addr + MOV WORD PTR [CALLXAD+2],AX ;AN000;;LB. + MOV AX,[TEMP_VAR] ;AN000;;LB. + MOV WORD PTR [CALLXAD],AX ;AN000;;LB. + MOV [SC_FLAG],0 ;AN000;;LB. reset sc_flag + MOV [CALLSCNT],1 ;AN000;;LB. one sector transferred + + TEST [DEVCALL.REQSTAT],STERR ;AN000;;LB. error? + JNZ scerror ;AN000;;LB. yes + PUSH DS ;AN000;;LB. + PUSH SI ;AN000;;LB. + PUSH ES ;AN000;;LB. + PUSH DI ;AN000;;LB. + PUSH DX ;AN000;;LB. + PUSH CX ;AN000;;LB. + XOR CX,CX ;AN000;;LB. we want first sector in SC + CALL SC2BUF2 ;AN000;;LB. move data from SC to buffer + POP CX ;AN000;;LB. + POP DX ;AN000;;LB. + POP DI ;AN000;;LB. + POP ES ;AN000;;LB. + POP SI ;AN000;;LB. + POP DS ;AN000;;LB. + JMP SHORT sc2end ;AN000;;LB. return + +scerror: ;AN000; + MOV [CALLSCNT],1 ;AN000;;LB. reset sector count to 1 + MOV [SC_STATUS],0 ;AN000;;LB. invalidate all SC sectors + MOV [CURSC_DRIVE],-1 ;AN000;;LB. invalidate drive + STC ;AN000;;LB. carry set + return ;AN000;;LB. + +sc2end: ;AN000; + CLC ;AN000;;LB. carry clear + return ;AN000;;LB. + +EndProc VIRREAD ;AN000; + +Break + +; Inputs: [SC_STATUS] = SC validity status +; [SC_SECTOR_SIZE] = request sector size +; [SC_CACHE_PTR] = pointer to SC +; Function: +; Move data from SC to buffer +; Output: +; carry clear, in SC and data is moved +; carry set, not in SC and data is not moved + + procedure SC2BUF,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + + CALL IN_SC ;AN000;;LB. in secondary cache + JC noSC ;AN000;;LB. no + MOV AX,1 ;AN000;;LB. check if valid sector + SHL AX,CL ;AN000;;LB. in the secondary cache + TEST [SC_STATUS],AX ;AN000;;LB. + JZ noSC ;AN000;;LB. invalid +entry SC2BUF2 ;AN000; + MOV AX,CX ;AN000;;LB. times index with + MUL [SC_SECTOR_SIZE] ;AN000;;LB. sector size + ADD AX,WORD PTR [SC_CACHE_PTR] ;AN000;;LB. add SC starting addr + ADC DX,WORD PTR [SC_CACHE_PTR+2];AN000;;LB. + MOV DS,DX ;AN000; ;LB. DS:SI-> SC sector addr + MOV SI,AX ;AN000; ;LB. + MOV ES,WORD PTR [CALLXAD+2] ;AN000; ;LB. ES:DI-> buffer addr + MOV DI,WORD PTR [CALLXAD] ;AN000; ;LB. + MOV CX,[SC_SECTOR_SIZE] ;AN000; ;LB. count= sector size + SHR CX,1 ;AN000; ;LB. may use DWORD move for 386 +entry MOVWORDS ;AN000; + CMP [DDMOVE],0 ;AN000; ;LB. 386 ? + JZ nodd ;AN000; ;LB. no + SHR CX,1 ;AN000; ;LB. words/2 + DB 66H ;AN000; ;LB. use double word move +nodd: + REP MOVSW ;AN000; ;LB. move to buffer + CLC ;AN000; ;LB. clear carry + return ;AN000; ;LB. exit +noSC: ;AN000; + STC ;AN000; ;LB. set carry +sexit: ;AN000; + return ;AN000; ;LB. + +EndProc SC2BUF +CODE ENDS + END + \ No newline at end of file diff --git a/v4.0/src/DOS/DINFO.ASM b/v4.0/src/DOS/DINFO.ASM new file mode 100644 index 0000000..10738b1 --- /dev/null +++ b/v4.0/src/DOS/DINFO.ASM @@ -0,0 +1,131 @@ +; SCCSID = @(#)dinfo.asm 1.1 85/04/10 +; SCCSID = @(#)dinfo.asm 1.1 85/04/10 +TITLE DISK_INFO - Internal Get Disk Info +NAME DISK_INFO +; Low level routine for returning disk drive information from a local +; or NET device +; +; DISK_INFO +; +; Modification history: +; +; Created: ARR 30 March 1983 +; + +; +; get the appropriate segment definitions +; +.xlist +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +.cref +.list + +Installed = TRUE + + i_need THISCDS,DWORD + i_need CURBUF,DWORD + i_need EXTERR_LOCUS,BYTE +if debug + I_need BugLev,WORD + I_need BugTyp,WORD +include bugtyp.asm +endif + +Break + +; Inputs: +; [THISCDS] Points to the Macro List Structure of interest +; (It MAY NOT be NUL, error not detected) +; Function: +; Get Interesting Drive Information +; Returns: +; DX = Number of free allocation units +; BX = Total Number of allocation units on disk +; CX = Sector size +; AL = Sectors per allocation unit +; AH = FAT ID BYTE +; Carry set if error (currently user FAILed to I 24) +; Segs except ES preserved, others destroyed + + procedure DISK_INFO,NEAR + DOSAssume CS,,"Disk_Info" + ASSUME ES:NOTHING + + Invoke TestNet + JNC LOCAL_INFO +IF NOT Installed + transfer NET_DISK_INFO +ELSE + MOV AX,(multNET SHL 8) OR 12 + INT 2FH + return +ENDIF + +LOCAL_INFO: + MOV [EXTERR_LOCUS],errLOC_Disk + EnterCrit critDisk + invoke FATREAD_CDS ; perform media check. + JC CRIT_LEAVE + MOV BX,2 + invoke UNPACK ; Get first FAT sector into CURBUF + JC CRIT_LEAVE + LDS SI,[CURBUF] +ASSUME DS:NOTHING + MOV AH,[SI].bufinsiz ; get FAT ID BYTE + context DS + MOV CX,ES:[BP.dpb_max_cluster] +; +; Examine the current free count. If it indicates that we have an invalid +; count, do the expensive calculation. +; + MOV DX,ES:[BP.dpb_free_cnt] ; get free count + CMP DX,-1 ; is it valid? + JZ DoScan +; +; Check to see if it is in a reasonalbe range. If so, trust it and return. +; Otherwise, we need to blast out an internal error message and then recompute +; the count. +; + CMP DX,CX ; is it in a reasonable range? + JB GotVal ; yes, trust it. + fmt TypInt,LevLog,<"Internal error: MaxClus <= FreeClus\n"> +DoScan: + XOR DX,DX + DEC CX +SCANFREE: + invoke UNPACK + JC Crit_Leave + JNZ NOTFREECLUS + INC DX ; A free one +NOTFREECLUS: + INC BX ; Next cluster + LOOP SCANFREE + DEC BX ; BX was next cluster. Convert to +ReturnVals: + DEC BX ; count + MOV AL,ES:[BP.dpb_cluster_mask] + INC AL ; Sectors/cluster + MOV CX,ES:[BP.dpb_sector_size] ; Bytes/sector + MOV ES:[BP.dpb_free_cnt],DX + CLC +CRIT_LEAVE: + LeaveCrit critDisk + return +; +; We have correctly computed everything previously. Load up registers for +; return. +; +GotVal: MOV BX,CX ; get cluster count + JMP ReturnVals + +EndProc DISK_INFO + +CODE ENDS + END diff --git a/v4.0/src/DOS/DIR.ASM b/v4.0/src/DOS/DIR.ASM new file mode 100644 index 0000000..2a86997 --- /dev/null +++ b/v4.0/src/DOS/DIR.ASM @@ -0,0 +1,445 @@ +; SCCSID = @(#)dir.asm 1.1 85/04/10 +; SCCSID = @(#)dir.asm 1.1 85/04/10 +TITLE DIR - Directory and path cracking +NAME Dir +; Main Path cracking routines, low level search routines +; +; FindEntry +; SEARCH +; Srch +; NEXTENT +; MetaCompare +; NEXTENTRY +; GETENTRY +; GETENT +; SETDIRSRCH +; SETROOTSRCH +; +; Revision history: +; +; A000 version 4.00 Jan. 1988 +; + +; +; get the appropriate segment definitions +; +.xlist +include dosseg.asm +include fastopen.inc + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +include dossym.inc +.cref +.list + +asmvar Kanji + + i_need EntFree,WORD + i_need DirStart,WORD + i_need LastEnt,WORD + i_need ClusNum,WORD + i_need CurBuf,DWORD + i_need Attrib,BYTE + i_need DelAll,BYTE + i_need VolID,BYTE + i_need Name1,BYTE + i_need ThisDPB,DWORD + i_need EntLast,WORD + i_need Creating,BYTE + i_need SecClusPos,BYTE + i_need ClusFac,BYTE + i_need NxtClusNum,WORD + i_need DirSec,DWORD ;AN000; + I_need FastOpenFlg,BYTE ;AN000; + I_need HIGH_SECTOR,WORD ;AN000; + +Break + +; Inputs: +; [THISDPB] set +; [SECCLUSPOS] = 0 +; [DIRSEC] = Starting directory sector number +; [CLUSNUM] = Next cluster of directory +; [CLUSFAC] = Sectors/Cluster +; [NAME1] = Name to look for +; Function: +; Find file name in disk directory. +; "?" matches any character. +; Outputs: +; Carry set if name not found +; ELSE +; Zero set if attributes match (always except when creating) +; AH = Device ID (bit 7 set if not disk) +; [THISDPB] = Base of drive parameters +; DS = DOSGROUP +; ES = DOSGROUP +; [CURBUF+2]:BX = Pointer into directory buffer +; [CURBUF+2]:SI = Pointer to First Cluster field in directory entry +; [CURBUF] has directory record with match +; [NAME1] has file name +; [LASTENT] is entry number of the entry +; All other registers destroyed. + + procedure SEARCH,near + + entry FindEntry + DOSAssume CS,,"FindEntry" + ASSUME ES:NOTHING + + invoke STARTSRCH + MOV AL,Attrib + AND AL,NOT attr_ignore ; Ignore useless bits + CMP AL,attr_volume_id ; Looking for vol ID only ? + JNZ NOTVOLSRCH ; No + CALL SETROOTSRCH ; Yes force search of root +NOTVOLSRCH: + CALL GETENTRY + JNC Srch + JMP SETESRET + + entry Srch + + PUSH DS + MOV DS,WORD PTR [CURBUF+2] +ASSUME DS:NOTHING + MOV AH,BYTE PTR [BX] + OR AH,AH ; End of directory? + JZ FREE + CMP AH,BYTE PTR [DELALL] ; Free entry? + JZ FREE + TEST BYTE PTR [BX+11],attr_volume_id + ; Volume ID file? + JZ CHKFNAM ; NO + INC BYTE PTR [VOLID] +CHKFNAM: +; Context ES + ASSUME ES:DOSGroup + MOV SI,SS + MOV ES,SI + MOV SI,BX + MOV DI,OFFSET DOSGROUP:NAME1 +;;;;; 7/29/86 + CMP BYTE PTR [NAME1],0E5H ; special char check + JNZ NO_E5 + MOV BYTE PTR [NAME1],05H +NO_E5: +;;;;; 7/29/86 + CALL MetaCompare + JZ FOUND + POP DS + + entry NEXTENT + DOSAssume CS,,"NextEnt" + + Assert ISDPB,<,>,"NextEnt" + LES BP,[THISDPB] +ASSUME ES:NOTHING + CALL NEXTENTRY + JNC SRCH + JMP SHORT SETESRET + +FREE: + POP DS + DOSAssume CS,,"DIR/Free" + MOV CX,[LASTENT] + CMP CX,[ENTFREE] + JAE TSTALL + MOV [ENTFREE],CX +TSTALL: + CMP AH,BYTE PTR [DELALL] ; At end of directory? +NextEntJ: + JZ NEXTENT ; No - continue search + MOV [ENTLAST],CX + STC + JMP SHORT SETESRET + +FOUND: +; +; We have a file with a matching name. We must now consider the attributes: +; ATTRIB Action +; ------ ------ +; Volume_ID Is Volume_ID in test? +; Otherwise If no create then Is ATTRIB+extra superset of test? +; If create then Is ATTRIB equal to test? +; + MOV CH,[SI] ; Attributes of file + POP DS + DOSAssume CS,,"DIR/found" + MOV AH,Attrib ; Attributes of search + AND AH,NOT attr_ignore + LEA SI,[SI+Dir_First-Dir_Attr] ; point to firclus field + TEST CH,attr_volume_id ; Volume ID file? + JZ check_one_volume_id ; Nope check other attributes + TEST AH,attr_volume_id ; Can we find Volume ID? + JZ NEXTENTJ ; Nope, (not even $FCB_CREATE) + XOR AH,AH ; Set zero flag for $FCB_CREATE + JMP SHORT RETFF ; Found Volume ID +check_one_volume_id: + CMP AH,attr_volume_id ; Looking only for Volume ID? + JZ NEXTENTJ ; Yes, continue search + invoke MatchAttributes + JZ RETFF + TEST BYTE PTR [CREATING],-1 ; Pass back mismatch if creating + JZ NEXTENTJ ; Otherwise continue searching +RETFF: + LES BP,[THISDPB] + MOV AH,ES:[BP.dpb_drive] +SETESRET: + PUSH SS + POP ES + return +EndProc Search + +; Inputs: +; DS:SI -> 11 character FCB style name NO '?' +; Typically this is a directory entry. It MUST be in upper case +; ES:DI -> 11 character FCB style name with possible '?' +; Typically this is a FCB or SFT. It MUST be in upper case +; Function: +; Compare FCB style names allowing for ? match to any char +; Outputs: +; Zero if match else NZ +; Destroys CX,SI,DI all others preserved + + procedure MetaCompare,near +ASSUME DS:NOTHING,ES:NOTHING + MOV CX,11 + IF DBCS ;AN000; +;-------------------- Start of DBCS ;AN000; + CMP BYTE PTR DS:[SI],05H ;AN000;; Special case for lead byte of 05h + JNE WILDCRD2 ;AN000;; Compare as normal if not an 05h + CMP BYTE PTR ES:[DI],0E5H ;AN000;; 05h and 0E5h equivalent for lead byte + JNE WILDCRD2 ;AN000;; Compare as normal if not an 05h + DEC CX ;AN000;; One less byte to compare + INC SI ;AN000;; Bypass lead byte in source and + INC DI ;AN000;; destination when 05h and 0E5h found. +WILDCRD2: ;AN000; + PUSH AX ;AN000;;KK. save ax +cagain: ;AN000;;KK. + CMP CX,0 ;AN000;;KK. end of compare ? + JLE metaend2 ;AN000;;KK. yes + MOV AL,[SI] ;AN000;;KK. is it a Kanji + invoke testkanj ;AN000;;KK. + JZ notdb ;AN000;;KK. no + MOV AX,'??' ;AN000;;KK. + CMP ES:[DI],AX ;AN000;;KK. is es:di pointing to '??' + JNZ metaend3 ;AN000;;KK. no + ADD SI,2 ;AN000;;KK. + ADD DI,2 ;AN000;;KK. update pointers and count +subcx: ;AN000; + SUB CX,2 ;AN000;;KK. + JMP cagain ;AN000;;KK. +metaend3: ;AN000;;KK. + CMPSW ;AN000;;KK. + JNZ metaend2 ;AN000;;KK. + JMP subcx ;AN000;;KK. +notdb: ;AN000; + CMPSB ;AN000;;KK. same code ? + JZ sameco ;AN000;;KK. yes + CMP BYTE PTR ES:[DI-1],"?" ;AN000;;KK. ? + JNZ metaend2 ;AN000;;KK. no +sameco: ;AN000; + DEC CX ;AN000;;KK. decrement count + JMP cagain ;AN000;;KK. + +metaend2: ;AN000; + POP AX ;AN000;;KK. +;-------------------- End of DBCS ;AN000; KK. + ELSE ;AN000; +WILDCRD: + REPE CMPSB + JZ MetaRet ; most of the time we will fail. +CHECK_META: + CMP BYTE PTR ES:[DI-1],"?" + JZ WildCrd +MetaRet: + ENDIF ;AN000; + return ; Zero set, Match +EndProc MetaCompare + +Break + +; Inputs: +; Same as outputs of GETENTRY, above +; Function: +; Update BX, and [LASTENT] for next directory entry. +; Carry set if no more. + +Procedure NextEntry + DOSAssume CS,,"NextEntry" + ASSUME ES:NOTHING + + MOV AX,[LASTENT] + CMP AX,[ENTLAST] + JZ NONE + INC AX + LEA BX,[BX+32] + CMP BX,DX + JB HAVIT + MOV BL,BYTE PTR [SECCLUSPOS] + INC BL + CMP BL,BYTE PTR [CLUSFAC] + JB SAMECLUS + MOV BX,[NXTCLUSNUM] + Invoke IsEOF + JAE NONE + CMP BX,2 + JB NONE + JMP GETENT + +NONE: + STC + return + +HAVIT: + MOV [LASTENT],AX + CLC + return + +SAMECLUS: + MOV BYTE PTR [SECCLUSPOS],BL + MOV [LASTENT],AX + PUSH DS + LDS DI,[CURBUF] +ASSUME DS:NOTHING + MOV DX,WORD PTR [DI.buf_sector+2] ;AN000; >32mb + MOV [HIGH_SECTOR],DX ;AN000; >32mb + MOV DX,WORD PTR [DI.buf_sector] ;AN000; >32mb + + ADD DX,1 ;AN000; >32mb + ADC [HIGH_SECTOR],0 ;AN000; >32mb + POP DS + DOSAssume CS,,"DIR/SameClus" + invoke FIRSTCLUSTER + XOR BX,BX + JMP SETENTRY +EndProc NextEntry + +; Inputs: +; [LASTENT] has directory entry +; ES:BP points to drive parameters +; [DIRSEC],[CLUSNUM],[CLUSFAC],[ENTLAST] set for DIR involved +; Function: +; Locates directory entry in preparation for search +; GETENT provides entry for passing desired entry in AX +; Outputs: +; [CURBUF+2]:BX = Pointer to next directory entry in CURBUF +; [CURBUF+2]:DX = Pointer to first byte after end of CURBUF +; [LASTENT] = New directory entry number +; [NXTCLUSNUM],[SECCLUSPOS] set via DIRREAD +; Carry set if error (currently user FAILed to I 24) + +Procedure GETENTRY,NEAR + DOSAssume CS,,"GetEntry" + ASSUME ES:NOTHING + + MOV AX,[LASTENT] + + entry GETENT + + Assert ISDPB,,"GetEntry/GetEnt" + MOV [LASTENT],AX +; +; Convert the entry number in AX into a byte offset from the beginning of the +; directory. +; + mov cl,5 ; shift left by 5 = mult by 32 + rol ax,cl ; keep hight order bits + mov dx,ax + and ax, NOT (32-1) ; mask off high order bits + and dx, 32-1 ; mask off low order bits +; +; DX:AX contain the byte offset of the required directory entry from the +; beginning of the directory. Convert this to a sector number. Round the +; sector size down to a multiple of 32. +; + MOV BX,ES:[BP.dpb_sector_size] + AND BL,255-31 ; Must be multiple of 32 + DIV BX + MOV BX,DX ; Position within sector + PUSH BX + invoke DIRREAD + POP BX + retc +SETENTRY: + MOV DX,WORD PTR [CURBUF] + ADD DX,BUFINSIZ + ADD BX,DX + ADD DX,ES:[BP.dpb_sector_size] ; Always clears carry + return +EndProc GetEntry + +Break + +; Inputs: +; BX cluster number of start of directory +; ES:BP Points to DPB +; DI next cluster number from fastopen extended info. DOS 3.3 only +; Function: +; Set up a directory search +; Outputs: +; [DIRSTART] = BX +; [CLUSFAC],[CLUSNUM],[SECCLUSPOS],[DIRSEC] set +; Carry set if error (currently user FAILed to I 24) +; destroys AX,DX,BX + + procedure SETDIRSRCH + DOSAssume CS,,"SetDirSrch" + ASSUME ES:NOTHING + + Assert ISDPB,,"SetDirSrch" + OR BX,BX + JZ SETROOTSRCH + MOV [DIRSTART],BX + MOV AL,ES:[BP.dpb_cluster_mask] + INC AL + MOV BYTE PTR [CLUSFAC],AL +; DOS 3.3 for FastOPen F.C. 6/12/86 + SaveReg + TEST [FastOpenFlg],Lookup_Success + JNZ UNP_OK + +; DOS 3.3 for FastOPen F.C. 6/12/86 + invoke UNPACK + JNC UNP_OK + RestoreReg + return + +UNP_OK: + MOV [CLUSNUM],DI + MOV DX,BX + XOR BL,BL + MOV BYTE PTR [SECCLUSPOS],BL + invoke FIGREC + RestoreReg + PUSH DX ;AN000; >32mb + MOV DX,[HIGH_SECTOR] ;AN000; >32mb + MOV WORD PTR [DIRSEC+2],DX ;AN000; >32mb + POP DX ;AN000; >32mb + MOV WORD PTR [DIRSEC],DX + CLC + return + +entry SETROOTSRCH + DOSAssume CS,,"SetRootSrch" + ASSUME ES:NOTHING + XOR AX,AX + MOV [DIRSTART],AX + MOV BYTE PTR [SECCLUSPOS],AL + DEC AX + MOV [CLUSNUM],AX + MOV AX,ES:[BP.dpb_first_sector] + MOV DX,ES:[BP.dpb_dir_sector] + SUB AX,DX + MOV BYTE PTR [CLUSFAC],AL + MOV WORD PTR [DIRSEC],DX ;F.C. >32mb + MOV WORD PTR [DIRSEC+2],0 ;F.C. >32mb + CLC + return +EndProc SETDIRSRCH + +CODE ENDS + END diff --git a/v4.0/src/DOS/DIR2.ASM b/v4.0/src/DOS/DIR2.ASM new file mode 100644 index 0000000..1346f43 --- /dev/null +++ b/v4.0/src/DOS/DIR2.ASM @@ -0,0 +1,1353 @@ +; SCCSID = @(#)dir2.asm 1.2 85/07/23 +; SCCSID = @(#)dir2.asm 1.2 85/07/23 +TITLE DIR2 - Directory and path cracking +NAME Dir2 +; Main Path cracking routines, low level search routines and device +; name detection routines +; +; GETPATH +; GetPathNoSet +; CHKDEV +; ROOTPATH +; FINDPATH +; StartSrch +; MatchAttributes +; DEVNAME +; Build_device_ent +; Validate_CDS +; CheckThisDevice +; +; Revision history: +; +; A000 version 4.00 Jan. 1988 +; A001 PTM 3564 -- search using fastopen + +; +; get the appropriate segment definitions +; +.xlist +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +include dossym.inc +include devsym.inc +include fastopen.inc ;DOS 3.3 +.cref +.list + +asmvar Kanji + + i_need NoSetDir,BYTE + i_need EntFree,WORD + i_need DirStart,WORD + i_need LastEnt,WORD + i_need WFP_START,WORD + i_need CURR_DIR_END,WORD + i_need CurBuf,DWORD + i_need THISCDS,DWORD + i_need Attrib,BYTE + i_need SAttrib,BYTE + i_need VolID,BYTE + i_need Name1,BYTE + i_need ThisDPB,DWORD + i_need EntLast,WORD + i_need Creating,BYTE + i_need NULDEV,DWORD + i_need DEVPT,DWORD + i_need DEVFCB,BYTE + i_need ALLOWED,BYTE + i_need EXTERR_LOCUS,BYTE + I_need FastOpenFlg,BYTE ;DOS 3.3 + I_need FastOpenTable,BYTE ;DOS 3.3 + I_need Dir_Info_Buff,BYTE ;DOS 3.3 + I_need FastOpen_Ext_Info,BYTE ;DOS 3.3 + I_need CLUSNUM,WORD ;DOS 3.3 + I_need Next_Element_Start,WORD ;DOS 3.3 + I_need HIGH_SECTOR,WORD ;AN000;>32mb + I_need DOS34_FLAG,WORD ;AN000;>32mb + + +Break + +; Inputs: +; [WFP_START] Points to WFP string ("d:\" must be first 3 chars, NUL +; terminated; d:/ (note forward slash) indicates a real device). +; [CURR_DIR_END] Points to end of Current dir part of string +; ( = -1 if current dir not involved, else +; Points to first char after last "/" of current dir part) +; [THISCDS] Points to CDS being used +; [SATTRIB] Is attribute of search, determines what files can be found +; [NoSetDir] set +; [THISDPB] set to DPB if disk otherwise garbage. +; Function: +; Crack the path +; Outputs: +; Sets EXTERR_LOCUS = errLOC_Disk if disk file +; Sets EXTERR_LOCUS = errLOC_Unk if char device +; ID1 field of [THISCDS] updated appropriately +; [ATTRIB] = [SATTRIB] +; ES:BP Points to DPB +; Carry set if bad path +; SI Points to path element causing failure +; Zero set +; [DIRSTART],[DIRSEC],[CLUSNUM], and [CLUSFAC] are set up to +; start a search on the last directory +; CL is zero if there is a bad name in the path +; CL is non-zero if the name was simply not found +; [ENTFREE] may have free spot in directory +; [NAME1] is the name. +; CL = 81H if '*'s or '?' in NAME1, 80H otherwise +; Zero reset +; File in middle of path or bad name in path or attribute mismatch +; or path too long or malformed path +; ELSE +; [CurBuf] = -1 if root directory +; [CURBUF] contains directory record with match +; [CURBUF+2]:BX Points into [CURBUF] to start of entry +; [CURBUF+2]:SI Points into [CURBUF] to dir_first field for entry +; AH = device ID +; bit 7 of AH set if device SI and BX +; will point DOSGROUP relative The firclus +; field of the device entry contains the device pointer +; [NAME1] Has name looked for +; If last element is a directory zero is set and: +; [DIRSTART],[SECCLUSPOS],[DIRSEC],[CLUSNUM], and [CLUSFAC] +; are set up to start a search on it. +; unless [NoSetDir] is non zero in which case the return is +; like that for a file (except for zero flag) +; If last element is a file zero is reset +; [DIRSEC],[CLUSNUM],[CLUSFAC],[NXTCLUSNUM],[SECCLUSPOS], +; [LASTENT], [ENTLAST] are set to continue search of last +; directory for furthur matches on NAME1 via the NEXTENT +; entry point in FindEntry (or GETENT entry in GETENTRY in +; which case [NXTCLUSNUM] and [SECCLUSPOS] need not be valid) +; DS preserved, Others destroyed + + procedure GETPATH,near + DOSAssume CS,,"GetPath" + ASSUME ES:NOTHING + + MOV WORD PTR [CREATING],0E500H ; Not Creating, not DEL *.* + +;Same as GetPath only CREATING and DELALL already set + entry GetPathNoSet + MOV [EXTERR_LOCUS],errLOC_Disk + MOV WORD PTR CurBuf,-1 ; initial setting +; +; See if the input indicates a device that has already been detected. If so, +; go build the guy quickly. Otherwise, let findpath find the device. +; + MOV DI,Wfp_Start ; point to the beginning of the name + CMP WORD PTR [DI+1],'\' SHL 8 + ':' + JZ CrackIt +; +; Let ChkDev find it in the device list +; + ADD DI,3 + MOV SI,DI ; let CHKDEV see the original name + CALL CHKDEV + JC InternalError +Build_devJ: + MOV AL,SAttrib + MOV Attrib,AL + MOV [EXTERR_LOCUS],errLOC_Unk ; In the particular case of + ; "finding" a char device + ; set LOCUS to Unknown. This makes + ; certain idiotic problems reported + ; by a certain 3 letter OEM go away. +; +; Take name in name1 and pack it back into where wfp_start points. This +; guarantees wfp_start pointing to a canonical representation of a device. +; We are allowed to do this as GetPath is *ALWAYS* called before entering a +; wfp into the share set. +; +; We copy chars from name1 to wfp_start remembering the position of the last +; non-space seen +1. This position is kept in DX. +; + Context ES + mov si,offset DOSGroup:Name1 + mov di,wfp_start + mov dx,di + mov cx,8 ; 8 chars in device name +MoveLoop: + lodsb + stosb + cmp al," " + jz nosave + IF DBCS ;AN000;; +; cmp al,81h ;AN000;; 2/23/KK +; jne notKanji ;AN000;; 2/23/KK +; cmp cx,1 ;AN000; 2/23/KK +; je notKanji ;AN000; 2/23/KK +; cmp byte ptr [si],40h ;AN000; 2/23/KK +; jne notKanji ;AN000;; 2/23/KK +; lodsb ;AN000;; 2/23/KK +; stosb ;AN000;; 2/23/KK +; dec cx ;AN000;; 2/23/KK +; jmp nosave ;AN000;; 2/23/KK +;notKanji: ;AN000;; 2/23/KK + ENDIF + mov dx,di +NoSave: + loop MoveLoop +; +; DX is the position of the last seen non-space + 1. We terminate the name +; at this point. +; + mov di,dx + mov byte ptr [di],0 ; end of string + invoke Build_device_ent ; Clears carry sets zero + INC AL ; reset zero + return + + assume es:nothing + +InternalError: + JMP InternalError ; freeze + +; +; Start off at the correct spot. Optimize if the current dir part is valid. +; +CrackIt: + MOV SI,[CURR_DIR_END] ; get current directory pointer + CMP SI,-1 ; valid? + JNZ LOOK_SING ; Yes, use it. + LEA SI,[DI+3] ; skip D:\ +LOOK_SING: + Assert ISDPB,<,>,"Crackit" + MOV Attrib,attr_directory+attr_system+attr_hidden + ; Attributes to search through Dirs + LES DI,[THISCDS] + MOV AX,-1 + MOV BX,ES:[DI.curdir_ID] + MOV SI,[CURR_DIR_END] +; +; AX = -1 +; BX = cluster number of current directory. THis number is -1 if the media +; has been uncertainly changed. +; SI = offset in DOSGroup into path to end of current directory text. This +; may be -1 if no current directory part has been used. +; + CMP SI,AX ; if Current directory is not part + JZ NO_CURR_D ; then we must crack from root + CMP BX,AX ; is the current directory cluster valid + +; DOS 3.3 6/25/86 + JZ NO_CURR_D ; no, crack form the root + TEST [FastOpenFlg],FastOpen_Set ; for fastopen ? + JZ GOT_SEARCH_CLUSTER ; no + PUSH ES ; save registers + PUSH DI + PUSH CX + PUSH [SI-1] ; save \ and 1st char of next element + PUSH SI + PUSH BX + + MOV BYTE PTR [SI-1],0 ; call fastopen to look up cur dir info + MOV SI,[Wfp_Start] + MOV BX,OFFSET DOSGROUP:FastOpenTable + MOV DI,OFFSET DOSGROUP:Dir_Info_Buff + MOV CX,OFFSET DOSGROUP:FastOpen_Ext_Info + MOV AL,FONC_look_up + PUSH DS + POP ES + CALL DWORD PTR [BX.FASTOPEN_NAME_CACHING] + JC GO_Chk_end1 ;fastopen not installed, or wrong drive. Go to Got_Srch_cluster + CMP BYTE PTR [SI],0 ;fastopen has current dir info? + JE GO_Chk_end ;yes. Go to got_serch_cluster + stc + jmp short GO_Chk_end ;Go to No_Curr_D +GO_Chk_end1: + clc +GO_Chk_end: ; restore registers + POP BX + POP SI + POP [SI-1] + POP CX + POP DI + POP ES + JNC GOT_SEARCH_CLUSTER ; crack based on cur dir + +; DOS 3.3 6/25/86 +; +; We must cract the path beginning at the root. Advance pointer to beginning +; of path and go crack from root. +; +NO_CURR_D: + MOV SI,[WFP_START] + LEA SI,[SI+3] ; Skip "d:/" + LES BP,[THISDPB] ; Get ES:BP + JMP ROOTPATH +; +; We are able to crack from the current directory part. Go set up for search +; of specified cluster. +; +GOT_SEARCH_CLUSTER: + LES BP,[THISDPB] ; Get ES:BP + invoke SETDIRSRCH + JC SETFERR + JMP FINDPATH + +SETFERR: + XOR CL,CL ; set zero + STC + Return + +EndProc GETPATH + +; Check to see if the name at DS:DI is a device. Returns carry set if not a +; device. +; Blasts CX,SI,DI,AX,BX + +Procedure ChkDev,NEAR + ASSUME ES:Nothing,DS:NOTHING + + MOV SI,DI + MOV DI,SS + MOV ES,DI + ASSUME ES:DOSGroup ; Now here is where ES is DOSGroup + + MOV DI,OFFSET DOSGROUP:NAME1 + MOV CX,9 +TESTLOOP: + invoke GETLET + IF DBCS ;AN000; + invoke Testkanj ;AN000;; 2/13/KK + jz Notkanja ;AN000;; 2/13/KK + stosb ;AN000;; Skip second byte 2/13/KK + dec cx ;AN000;; 2/13/KK + jcxz notdev ;AN000;; 2/13/KK + lodsb ;AN000;; 2/13/KK + jmp short stowit ;AN000;; 2/13/KK +Notkanja: ;AN000; + ENDIF ;AN000; + CMP AL,'.' + JZ TESTDEVICE + invoke PATHCHRCMP + JZ NOTDEV + OR AL,AL + JZ TESTDEVICE +stowit: + STOSB + LOOP TESTLOOP +NOTDEV: + STC + return + +TESTDEVICE: + ADD CX,2 + MOV AL,' ' + REP STOSB + MOV AX,SS + MOV DS,AX + invoke DEVNAME + return +EndProc ChkDev + +Break + +; Inputs: +; Same as FINDPATH but, +; SI Points to asciz string of path which is assumed to start at +; the root (no leading '/'). +; Function: +; Search from root for path +; Outputs: +; Same as FINDPATH but: +; If root directory specified, [CURBUF] and [NAME1] are NOT set, and +; [NoSetDir] is ignored. + + procedure ROOTPATH,near + + DOSAssume CS,,"RootPath" + ASSUME ES:NOTHING + + invoke SETROOTSRCH + CMP BYTE PTR [SI],0 + JNZ FINDPATH + +; Root dir specified + MOV AL,SAttrib + MOV Attrib,AL + XOR AH,AH ; Sets "device ID" byte, sets zero + ; (dir), clears carry. + return + +; Inputs: +; [ATTRIB] Set to get through directories +; [SATTRIB] Set to find last element +; ES:BP Points to DPB +; SI Points to asciz string of path (no leading '/'). +; [SECCLUSPOS] = 0 +; [DIRSEC] = Phys sec # of first sector of directory +; [CLUSNUM] = Cluster # of next cluster +; [CLUSFAC] = Sectors per cluster +; [NoSetDir] set +; [CURR_DIR_END] Points to end of Current dir part of string +; ( = -1 if current dir not involved, else +; Points to first char after last "/" of current dir part) +; [THISCDS] Points to CDS being used +; [CREATING] and [DELALL] set +; Function: +; Parse path name +; Outputs: +; ID1 field of [THISCDS] updated appropriately +; [ATTRIB] = [SATTRIB] +; ES:BP Points to DPB +; [THISDPB] = ES:BP +; Carry set if bad path +; SI Points to path element causing failure +; Zero set +; [DIRSTART],[DIRSEC],[CLUSNUM], and [CLUSFAC] are set up to +; start a search on the last directory +; CL is zero if there is a bad name in the path +; CL is non-zero if the name was simply not found +; [ENTFREE] may have free spot in directory +; [NAME1] is the name. +; CL = 81H if '*'s or '?' in NAME1, 80H otherwise +; Zero reset +; File in middle of path or bad name in path +; or path too long or malformed path +; ELSE +; [CURBUF] contains directory record with match +; [CURBUF+2]:BX Points into [CURBUF] to start of entry +; [CURBUF+2]:SI Points to fcb_FIRCLUS field for entry +; [NAME1] Has name looked for +; AH = device ID +; bit 7 of AH set if device SI and BX +; will point DOSGROUP relative The firclus +; field of the device entry contains the device pointer +; If last element is a directory zero is set and: +; [DIRSTART],[SECCLUSPOS],[DIRSEC],[CLUSNUM], and [CLUSFAC] +; are set up to start a search on it, +; unless [NoSetDir] is non zero in which case the return is +; like that for a file (except for zero flag) +; If last element is a file zero is reset +; [DIRSEC],[CLUSNUM],[CLUSFAC],[NXTCLUSNUM],[SECCLUSPOS], +; [LASTENT], [ENTLAST] are set to continue search of last +; directory for furthur matches on NAME1 via the NEXTENT +; entry point in FindEntry (or GETENT entry in GETENTRY in +; which case [NXTCLUSNUM] and [SECCLUSPOS] need not be valid) +; Destroys all other registers + + entry FINDPATH + DOSAssume CS,,"FindPath" + ASSUME ES:NOTHING + + Assert ISDPB,,"FindPath" + PUSH ES ; Save ES:BP + PUSH SI + MOV DI,SI + MOV CX,[DIRSTART] ; Get start clus of dir being searched + CMP [CURR_DIR_END],-1 + JZ NOIDS ; No current dir part + CMP DI,[CURR_DIR_END] + JNZ NOIDS ; Not to current dir end yet + LES DI,[THISCDS] + MOV ES:[DI.curdir_ID],CX ; Set current directory currency +NOIDS: +; +; Parse the name off of DS:SI into NAME1. AL = 1 if there was a meta +; character in the string. CX,DI may be destroyed. +; +; invoke NAMETRANS +; MOV CL,AL +; +; The above is the slow method. The name has *already* been munged by +; TransPath so no special casing needs to be done. All we do is try to copy +; the name until ., \ or 0 is hit. +; + MOV AX,SS + MOV ES,AX + MOV DI,OFFSET DOSGroup:Name1 + MOV AX,' ' + STOSB + STOSW + STOSW + STOSW + STOSW + STOSW + MOV DI,OFFSET DOSGroup:Name1 + XOR AH,AH ; bits for CL + IF DBCS ;AN000; +;-------------------------- Start of DBC;AN000;S 2/13/KK + XOR CL,CL ;AN000;; clear count for volume id + LODSB ;AN000;;IBMJ fix 9/04/86 + CMP AL,05h ;AN000;;IBMJ fix 9/04/86 + JNE GetNam2 ;AN000;;IBMJ fix 9/04/86 + PUSH AX ;AN000; ;IBMJ fix 9/04/86 + MOV AL,0E5h ;AN000;;IBMJ fix 9/04/86 + Invoke TestKanj ;AN000;;IBMJ fix 9/04/86 + POP AX ;AN000; ;IBMJ fix 9/04/86 + JZ Notkanjb ;AN000; ;IBMJ fix 9/04/86 + JMP SHORT GetNam3 ;AN000;;IBMJ fix 9/04/86 +;-------------------------- End of DBCS ;AN000;2/13/KK + ENDIF +GetNam: + INC CL ;AN000; KK incrment volid count + LODSB + IF DBCS ;AN000; +GetNam2: ;AN000;; 2/13/KK + invoke Testkanj ;AN000;; 2/13/KK + jz Notkanjb ;AN000;; 2/13/KK +GetNam3: ;AN000;; 2/13/KK + STOSB ;AN000;; 2/13/KK + INC CL ;AN000;; KK incrment volid count + LODSB ;AN000;; 2/13/KK + TEST [DOS34_FLAG],DBCS_VOLID ;AN000;; 2/13/KK + JZ notvol ;AN000;; 2/13/KK + CMP CL,8 ;AN000;; 2/13/KK + JNZ notvol ;AN000;; 2/13/KK + CMP AL,'.' ;AN000;; 2/13/KK + JNZ notvol ;AN000;; 2/13/KK + LODSB ;AN000;; 2/13/KK +notvol: ;AN000; + jmp short StoNam ;AN000;; 2/13/KK +Notkanjb: ;AN000;; 2/13/KK + ENDIF ;AN000; + CMP AL,'.' + JZ setExt + OR AL,AL + JZ GetDone + CMP AL,'\' + JZ GetDone + CMP AL,'?' + JNZ StoNam + OR AH,1 +StoNam: STOSB + JMP GetNam +SetExt: + MOV DI,OFFSET DOSGroup:Name1+8 +GetExt: + LODSB + IF DBCS ;AN000; + invoke TestKanj ;AN000;; 2/13/KK + jz Notkanjc ;AN000;; 2/13/KK + STOSB ;AN000;; 2/13/KK + LODSB ;AN000;; 2/13/KK + jmp short StoExt ;AN000;; 2/13/KK +Notkanjc: ;AN000;; 2/13/KK + ENDIF ;AN000; + OR AL,AL + JZ GetDone + CMP AL,'\' + JZ GetDone + CMP AL,'?' + JNZ StoExt + OR AH,1 +StoExt: STOSB + JMP GetExt +GetDone: + DEC SI + MOV CL,AH + + + OR CL,80H + POP DI ; Start of this element + POP ES ; Restore ES:BP + CMP SI,DI + JNZ check_device + JMP BADPATH ; NUL parse (two delims most likely) +check_device: + PUSH SI ; Start of next element + MOV AL,BYTE PTR [SI] + OR AL,AL + JNZ NOT_LAST + +; +; for last element of the path switch to the correct search attributes +; + MOV BH,SAttrib + MOV Attrib,BH +NOT_LAST: + +; +; check name1 to see if we have a device... +; + PUSH ES ; Save ES:BP + context ES + invoke DevName ; blast BX + POP ES ; Restore ES:BP + ASSUME ES:NOTHING + JC FindFile ; Not a device + OR AL,AL ; Test next char again + JZ GO_BDEV + JMP FileInPath ; Device name in middle of path + +GO_BDEV: + POP SI ; Points to NUL at end of path + JMP Build_devJ + +FindFile: + ASSUME ES:NOTHING +;;;; 7/28/86 + CMP BYTE PTR [NAME1],0E5H ; if 1st char = E5 + JNZ NOE5 ; no + MOV BYTE PTR [NAME1],05H ; change it to 05 +NOE5: + +;;;; 7/28/86 + PUSH DI ; Start of this element + PUSH ES ; Save ES:BP + PUSH CX ; CL return from NameTrans +;DOS 3.3 FastOPen 6/12/86 F.C. + + CALL LookupPath ; call fastopen to get dir entry + JNC DIR_FOUND ; found dir entry + +;DOS 3.3 FastOPen 6/12/86 F.C. + invoke FINDENTRY +DIR_FOUND: + POP CX + POP ES + POP DI + JNC LOAD_BUF + JMP BADPATHPOP + +LOAD_BUF: + LDS DI,[CURBUF] +ASSUME DS:NOTHING + TEST BYTE PTR [BX+dir_attr],attr_directory + JNZ GO_NEXT ; DOS 3.3 + JMP FileInPath ; Error or end of path +; +; if we are not setting the directory, then check for end of string +; +GO_NEXT: + CMP BYTE PTR [NoSetDir],0 + JZ SetDir + MOV DX,DI ; Save pointer to entry + MOV CX,DS + context DS + POP DI ; Start of next element + TEST [FastOpenFlg],FastOpen_Set ;only DOSOPEN can take advantage of + JZ nofast ; the FastOpen + TEST [FastOpenFlg],Lookup_Success ; Lookup just happened + JZ nofast ; no + MOV DI,[Next_Element_Start] ; no need to insert it again +nofast: + CMP BYTE PTR [DI],0 + JNZ NEXT_ONE ; DOS 3.3 + JMP SetRet ; Got it +NEXT_ONE: + PUSH DI ; Put start of next element back on stack + MOV DI,DX + MOV DS,CX ; Get back pointer to entry +ASSUME DS:NOTHING + +SetDir: + MOV DX,[SI] ; Dir_first + +;DOS 3.3 FastOPen 6/12/86 F.C. + + PUSH DS ; save [curbuf+2] + context DS ; set DS Dosgroup + TEST [FastOpenFlg],Lookup_Success ; + JZ DO_NORMAL ; fastopen not in memory or path not + MOV BX,DX ; not found + MOV DI,[CLUSNUM] ; clusnum was set in LookupPath + PUSH AX ; save device id (AH) + invoke SETDIRSRCH + POP AX ; restore device id (AH) + ADD SP,2 ; pop ds in stack + JMP FAST_OPEN_SKIP + +DO_NORMAL: +ASSUME DS:NOTHING + POP DS ; DS = [curbuf + 2] +;DOS 3.3 FastOPen 6/12/86 F.C. + + SUB BX,DI ; Offset into sector of start of entry + SUB SI,DI ; Offset into sector of dir_first + PUSH BX + PUSH AX + PUSH SI + PUSH CX + PUSH WORD PTR [DI.buf_sector] ;AN000;>32mb + PUSH WORD PTR [DI.buf_sector+2] ;AN000;>32mb + MOV BX,DX + context DS + invoke SETDIRSRCH ; This uses UNPACK which might blow + ; the entry sector buffer + POP [HIGH_SECTOR] + POP DX + JC SKIP_GETB + MOV [ALLOWED],allowed_RETRY + allowed_FAIL + XOR AL,AL + invoke GETBUFFR ; Get the entry buffer back +SKIP_GETB: + POP CX + POP SI + POP AX + POP BX + JNC SET_THE_BUF + POP DI ; Start of next element + MOV SI,DI ; Point with SI + JMP SHORT BADPATH + +SET_THE_BUF: + invoke SET_BUF_AS_DIR + MOV DI,WORD PTR [CURBUF] + ADD SI,DI ; Get the offsets back + ADD BX,DI +; DOS 3.3 FasOpen 6/12/86 F.C. + +FAST_OPEN_SKIP: + + POP DI ; Start of next element + CALL InsertPath ; insert dir entry info + +; DOS 3.3 FasOpen 6/12/86 F.C. + + + MOV AL,[DI] + OR AL,AL + JZ SETRET ; At end + INC DI ; Skip over "/" + MOV SI,DI ; Point with SI + invoke PATHCHRCMP + JNZ find_bad_name ; oops + JMP FINDPATH ; Next element + +find_bad_name: + DEC SI ; Undo above INC to get failure point +BADPATH: + XOR CL,CL ; Set zero + JMP SHORT BADPRET + +FILEINPATH: + POP DI ; Start of next element + context DS ; Got to from one place with DS gone +; DOS 3.3 FastOpen + + TEST [FastOpenFlg],FastOpen_Set ; do this here is we don't want to + JZ NO_FAST ; device info to fastopen + TEST [FastOpenFlg],Lookup_Success + JZ NO_FAST + MOV DI,[Next_Element_Start] ; This takes care of one time lookup + ; success +NO_FAST: + +; DOS 3.3 FastOpen + + MOV AL,[DI] + OR AL,AL + JZ INCRET + MOV SI,DI ; Path too long + JMP SHORT BADPRET + +INCRET: +; DOS 3.3 FasOpen 6/12/86 F.C. + + CALL InsertPath ; insert dir entry info + +; DOS 3.3 FasOpen 6/12/86 F.C. + INC AL ; Reset zero +SETRET: + return + +BADPATHPOP: + POP SI ; Start of next element + MOV AL,[SI] + MOV SI,DI ; Start of bad element + OR AL,AL ; zero if bad element is last, non-zero if path too long +BADPRET: + MOV AL,SAttrib + MOV Attrib,AL ; Make sure return correct + STC + return +EndProc ROOTPATH + +Break + +; Inputs: +; [THISDPB] Set +; Function: +; Set up a search for GETENTRY and NEXTENTRY +; Outputs: +; ES:BP = Drive parameters +; Sets up LASTENT, ENTFREE=ENTLAST=-1, VOLID=0 +; Destroys ES,BP,AX + + procedure StartSrch,NEAR + DOSAssume CS,,"StartSrch" + ASSUME ES:NOTHING + + Assert ISDPB,<,>,"StartSrch" + LES BP,[THISDPB] + XOR AX,AX + MOV [LASTENT],AX + MOV BYTE PTR [VOLID],AL ; No volume ID found + DEC AX + MOV [ENTFREE],AX + MOV [ENTLAST],AX + return +EndProc StartSrch + +BREAK + +; +; Input: [Attrib] = attribute to search for +; CH = found attribute +; Output: JZ +; JNZ +; Registers modified: noneski + procedure MatchAttributes,near + ASSUME DS:NOTHING,ES:NOTHING + PUSH AX + MOV AL,Attrib ; AL <- SearchSet + NOT AL ; AL <- SearchSet' + AND AL,CH ; AL <- SearchSet' and FoundSet + AND AL,attr_all ; AL <- SearchSet' and FoundSet and Important +; +; the result is non-zero if an attribute is not in the search set +; and in the found set and in the important set. This means that we do not +; have a match. Do a JNZ or JZ +; + POP AX + return +EndProc MatchAttributes + +Break + +; Inputs: +; DS,ES:DOSGROUP +; Filename in NAME1 +; ATTRIB set so that we can error out if looking for Volume IDs +; Function: +; Determine if file is in list of I/O drivers +; Outputs: +; Carry set if not a device +; ELSE +; Zero flag set +; BH = Bit 7,6 = 1, bit 5 = 0 (cooked mode) +; bits 0-4 set from low byte of attribute word +; DEVPT = DWORD pointer to Device header of device +; BX destroyed, others preserved + + procedure DEVNAME,NEAR + DOSAssume CS,,"DevName" + + PUSH SI + PUSH DI + PUSH CX + PUSH AX + +; E5 special code + PUSH WORD PTR [NAME1] + CMP [NAME1],5 + JNZ NOKTR + MOV [NAME1],0E5H +NOKTR: + + TEST Attrib,attr_volume_id ; If looking for VOL id don't find devs + JNZ RET31 + MOV SI,OFFSET DOSGROUP:NULDEV +LOOKIO: +ASSUME DS:NOTHING + TEST [SI.SDEVATT],DEVTYP + JZ SKIPDEV ; Skip block devices (NET and LOCAL) + MOV AX,SI + ADD SI,SDEVNAME + MOV DI,OFFSET DOSGROUP:NAME1 + MOV CX,4 ; All devices are 8 letters + REPE CMPSW ; Check for name in list + MOV SI,AX + JZ IOCHK ; Found it? +SKIPDEV: + LDS SI,DWORD PTR [SI] ; Get address of next device + CMP SI,-1 ; At end of list? + JNZ LOOKIO +RET31: STC ; Not found +RETNV: MOV CX,SS + MOV DS,CX + ASSUME DS:DOSGroup + POP WORD PTR [NAME1] + POP AX + POP CX + POP DI + POP SI + RET + +IOCHK: +ASSUME DS:NOTHING + MOV WORD PTR [DEVPT+2],DS ; Save pointer to device + MOV BH,BYTE PTR [SI.SDEVATT] + OR BH,0C0H + AND BH,NOT 020H ; Clears Carry + MOV WORD PTR [DEVPT],SI + JMP RETNV +EndProc DevName + +BREAK + +; Inputs: +; [NAME1] has name +; BH is attribute field (supplied by DEVNAME) +; [DEVPT] points to device header (supplied by DEVNAME) +; Function: +; Build a directory entry for a device at DEVFCB +; Outputs: +; BX points to DEVFCB +; SI points to dir_first field +; AH = input BH +; AL = 0 +; dir_first = DEVPT +; Zero Set, Carry Clear +; DS,ES,BP preserved, others destroyed + + procedure Build_device_ent,near + DOSAssume CS,,"Build_Device_Ent" + + MOV AX," " + MOV DI,OFFSET DOSGROUP:DEVFCB+8 ; Point to extent field +; +; Fill dir_ext +; + STOSW + STOSB ; Blank out extent field + MOV AL,attr_device +; +; Fill Dir_attr +; + STOSB ; Set attribute field + XOR AX,AX + MOV CX,10 +; +; Fill dir_pad +; + REP STOSW ; Fill rest with zeros + invoke DATE16 + MOV DI,OFFSET DOSGROUP:DEVFCB+dir_time + XCHG AX,DX +; +; Fill dir_time +; + STOSW + XCHG AX,DX +; +; Fill dir_date +; + STOSW + MOV SI,DI ; SI points to dir_first field + MOV AX,WORD PTR [DEVPT] +; +; Fill dir_first +; + STOSW ; Dir_first points to device + MOV AX,WORD PTR [DEVPT+2] +; +; Fill dir_size_l +; + STOSW + MOV AH,BH ; Put device atts in AH + MOV BX,OFFSET DOSGROUP:DEVFCB + XOR AL,AL ; Set zero, clear carry + return +EndProc Build_device_ent + +Break + +; +; ValidateCDS - Get current CDS. Splice it. Call FatReadCDS to check +; media. If media has been changed, do DOS_Chdir to validate path. If +; invalid, reset original CDS to root. +; +; Inputs: ThisCDS points to CDS of interest +; SS:DI points to temp buffer +; Outputs: The current directory string is validated on the appropriate +; drive +; ThisDPB changed +; ES:DI point to CDS +; Carry set if error (currently user FAILed to I 24) +; Registers modified: all + +Procedure ValidateCDS,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup +Public DIR2001S,DIR2001E +DIR2001S: + LocalVar Temp,WORD + LocalVar SaveCDS,DWORD +DIR2001E: + Enter + MOV Temp,DI + LDS SI,ThisCDS + MOV SaveCDSL,SI + MOV SaveCDSH,DS + EnterCrit critDisk + TEST [SI].curdir_flags,curdir_isnet ; Clears carry + JZ DoSplice + JMP FatFail +DoSplice: + XOR DL,DL + XCHG DL,NoSetDir + Context ES + Invoke FStrcpy + MOV SI,Temp + Context DS + Invoke Splice + ASSUME DS:NOTHING + Context DS ; FatReadCDS (ThisCDS); + MOV NoSetDir,DL + LES DI,ThisCDS + SaveReg + Invoke FatRead_CDS + RestoreReg + JC FatFail + LDS SI,ThisCDS ; if (ThisCDS->ID == -1) { + ASSUME DS:NOTHING + CMP [SI].curdir_ID,-1 + JNZ RestoreCDS + Context ES + SaveReg ; t = wfp_Start; + CMP SI,SaveCDSL ; if not spliced + JNZ DoChdir + MOV DI,Temp + MOV wfp_Start,DI ; wfp_start = d; + Invoke FStrCpy ; strcpy (d, ThisCDS->Text); +DoChdir: + Context DS + SaveReg <,BP> ; c = DOSChDir (); + Invoke DOS_ChDir + RestoreReg ; wfp_Start = t; + MOV SAttrib,BL + LDS SI,SaveCDS + ASSUME DS:NOTHING + JNC SetCluster ; if (c == -1) { + MOV WORD PTR ThisCDS,SI ; ThisCDS = TmpCDS; + MOV WORD PTR ThisCDS+2,DS + XOR CX,CX ; TmpCDS->text[3] = c = 0; + MOV [SI+3],CL ; } +SetCluster: + MOV [SI].curdir_ID,-1 ; TmpCDS->ID = -1; + LDS SI,ThisCDS ; ThisCDS->ID = c; + TEST [SI].curdir_flags,curdir_splice ;AN000;;MS. for Join and Subst + JZ setdirclus ;AN000;;MS. + MOV CX,-1 ;AN000;;MS. +setdirclus: + MOV [SI].curdir_ID,CX ; } +RestoreCDS: + LES DI,SaveCDS + MOV WORD PTR ThisCDS,DI + MOV WORD PTR ThisCDS+2,ES + CLC +FatFail: + LeaveCrit critDisk + LES DI,SaveCDS + Leave + return +EndProc ValidateCDS + +Break + +; +; CheckThisDevice - Examine the area at DS:SI to see if there is a valid +; device specified. We will return carry if there is a device present. The +; forms of devices we will recognize are: +; +; [path]device +; +; Note that the drive letter has *already* been removed. All other forms +; are not considered to be devices. If such a device is found we change the +; source pointer to point to the device component. +; +; Inputs: ES is DOSGroup +; DS:SI contains name +; Outputs: ES is DOSGroup +; DS:SI point to name or device +; Carry flag set if device was found +; Carry flag reset otherwise +; Registers Modified: all except ES:DI, DS + +if FALSE +Procedure CheckThisDevice,NEAR + DOSAssume CS,,"CheckThisDevice" + ASSUME DS:NOTHING + SaveReg +; +; Advance to after the final path character. +; + MOV DI,SI ; remember first character +PathSkip: + LODSB + OR AL,AL + JZ FoundEnd + IF DBCS ;AN000; + invoke Testkanj ;AN000;; 2/13/KK + jz Notkanje ;AN000;; 2/13/KK + lodsb ;AN000;; 2/13/KK + or al,al ;AN000;; Skip second byte 2/13/KK removed + jz FoundEnd ;AN000;; 2/13/KK removed + jmp Short Pathskip ;AN000;; Ignore missing second byte for now. +NotKanje: ;AN000; + ENDIF ;AN000; +;kanji load of next char too 2/13/KK +IF Kanji + kanji load of next char too +ENDIF + invoke PathChrCmp ; is it a path char? + JNZ PathSkip + MOV DI,SI + JMP PathSkip +FoundEnd: + MOV SI,DI +; +; Parse the name +; + SaveReg ; preserve the source pointer + invoke NameTrans ; advance DS:SI + CMP BYTE PTR [SI],0 ; parse entire string? + STC ; simulate a Carry return from DevName + JNZ SkipSearch ; no parse. simulate a file return. + Context DS + Invoke DevName + ASSUME DS:NOTHING +SkipSearch: + RestoreReg +; +; DS:SI points to the beginning of the potential device. If we have a device +; then we do not change SI. If we have a file, then we reset SI back to the +; original value. At this point Carry set indicates FILE. +; + RestoreReg ; get original SI + JNC CheckDone ; if device then do not reset pointer + MOV SI,DI +CheckDone: + RestoreReg + CMC ; invert carry. Carry => device + return +else +Procedure CheckThisDevice,NEAR + DOSAssume CS,,"CheckThisDevice" + ASSUME DS:NOTHING + SaveReg + MOV DI,SI +; +; Check for presence of \dev\ (Dam multiplan!) +; + MOV AL,[SI] + Invoke PathChrCmp ; is it a path char? + JNZ ParseDev ; no, go attempt to parse device + INC SI ; simulate LODSB +; +; We have the leading path separator. Look for DEV part. +; + LODSW + OR AX,2020h + CMP AX,"e" SHL 8 + "d" + JNZ NotDevice ; not "de", assume not device + LODSB + OR AL,20h + CMP AL,"v" ; Not "v", assume not device + JNZ NotDevice + LODSB + invoke PathChrCmp ; do we have the last path separator? + JNZ NotDevice ; no. go for it. +; +; DS:SI now points to a potential drive. Preserve them as NameTrans advances +; SI and DevName may destroy DS. +; +ParseDev: + SaveReg ; preserve the source pointer + invoke NameTrans ; advance DS:SI + CMP BYTE PTR [SI],0 ; parse entire string? + STC ; simulate a Carry return from DevName + JNZ SkipSearch ; no parse. simulate a file return. + Context DS + Invoke DevName + ASSUME DS:NOTHING +SkipSearch: + RestoreReg +; +; SI points to the beginning of the potential device. If we have a device +; then we do not change SI. If we have a file, then we reset SI back to the +; original value. At this point Carry set indicates FILE. +; +CheckReturn: + RestoreReg ; get original SI + JNC CheckDone ; if device then do not reset pointer + MOV SI,DI +CheckDone: + RestoreReg + CMC ; invert carry. Carry => device + return +NotDevice: + STC + JMP CheckReturn +endif + +EndProc CheckThisDevice + +BREAK + +; +; Output DS:SI -> path name, +; ES:DI -> dir entry info buffer +; ES:CX -> extended dir info buffer +; +; carry flag clear : tables pointed by ES:DI and ES:CX are filled by +; FastOpen, DS:SI points to char just one after +; the last char of path name which is fully or +; partially found in FastOPen +; carry flag set : FastOpen not in memory or path name not found +; + procedure LookupPath,NEAR + ASSUME ES:NOTHING + +; PUSH AX + TEST [FastOpenFlg],FastOpen_Set ; flg is set in DOSPEN + JNZ FASTINST ; and this routine is +NOLOOK: + JMP NOLOOKUP ; executed once +FASTINST: + TEST [FastOpenFlg],No_Lookup ; no more lookup? + JNZ NOLOOK ; yes + + MOV BX,OFFSET DOSGROUP:FastOpenTable ; get fastopen related tab + MOV SI,[Wfp_Start] ; si points to path name + MOV DI,OFFSET DOSGROUP:Dir_Info_Buff + MOV CX,OFFSET DOSGROUP:FastOpen_Ext_Info + MOV AL,FONC_look_up ; al = 1 + PUSH DS + POP ES + CALL DWORD PTR [BX.FASTOPEN_NAME_CACHING] ;call fastopen + JC NOTFOUND ; fastopen not in memory + + LEA BX,[SI-2] + CMP BX,[Wfp_Start] ; path found ? + JZ NOTFOUND ; no + ; fully or partially found + CMP BYTE PTR [SI],0 ;AN000;FO. + JNZ parfnd ;AN000;FO.; partiallyfound + PUSH CX ;AN000;FO.; is attribute matched ? + MOV CL,Attrib ;AN000;FO.; + MOV CH,Sattrib ;AN000;FO.; attrib=sattrib + MOV Attrib,CH ;AN000;FO.; + MOV CH,ES:[DI.dir_attr] ;AN000;FO.; + invoke Matchattributes ;AN000;FO.; +;;; MOV Attrib,CL ;AN001;FO.; retore attrib + POP CX ;AN000;FO.; + JNZ NOLOOKUP ;AN000;FO.; not matched +parfnd: + MOV [Next_Element_Start],SI ; save si + MOV BX,CX + MOV AX,[BX.FEI_lastent] ;AN000;;FO. restore lastentry + MOV [LASTENT],AX ;AN000;;FO. + MOV AX,[BX.FEI_dirstart] ;AN001;;FO. restore dirstart + MOV [DIRSTART],AX ;AN001;;FO. + MOV AX,[BX.FEI_clusnum] ; restore next cluster num + MOV [CLUSNUM],AX ; + + PUSH ES ; save ES + LES BX,[THISDPB] ; put drive id + MOV AH,ES:[BX.dpb_drive] ; in AH for DOOPEN + POP ES ; pop ES + + MOV WORD PTR [CURBUF+2],ES ; [curbuf+2].bx points to + MOV BX,DI ; start of entry + LEA SI,[DI.dir_first] ; [curbuf+2]:si points to + ; dir_first field in the + ; dir entry + OR [FastOpenFlg],Lookup_Success + set_for_search +; POP AX + RET +NOTFOUND: + CMP AX,-1 ; not in memory ? + JNZ Partial_Success ; yes, in memory + MOV [FastOpenFlg],0 ; no more fastopen +Partial_Success: + AND [FastOpenFlg],Special_Fill_Reset +NOLOOKUP: +; POP AX + STC + RET +EndProc LookupPath + +BREAK + +; +; Input: FastOpen_Set flag set when from DOSOPEN otherwise 0 +; Lookup_Success flag set when got dir entry info from FASTOPEN +; DS = DOSGROUP +; Output: FastOPen_Ext_Info is set and path dir info is inserted +; + procedure InsertPath,NEAR + ASSUME ES:NOTHING + + PUSHF + TEST [FastOpenFlg],FastOpen_Set ;only DOSOPEN can take advantage of + JZ GET_NEXT_ELEMENT ; the FastOpen + TEST [FastOpenFlg],Lookup_Success ; Lookup just happened + JZ INSERT_DIR_INFO ; no + AND [FastOpenFlg],Lookup_Reset ; we got dir info from fastopen so + MOV DI,[Next_Element_Start] ; no need to insert it again + JMP GET_NEXT2 +INSERT_DIR_INFO: ; save registers + PUSH DS + PUSH ES + PUSH BX + PUSH SI + PUSH DI + PUSH CX + PUSH AX +; int 3 + LDS DI,[CURBUF] ; DS:DI -> buffer header +ASSUME DS:NOTHING + MOV SI,OFFSET DOSGROUP:FastOpen_Ext_Info + MOV AX,WORD PTR [DI.buf_sector] ; get directory sector + MOV WORD PTR CS:[SI.FEI_dirsec],AX ;AN000; >32mb save dir sector + MOV AX,WORD PTR [DI.buf_sector+2] ;AN000; >32mb + context DS + MOV WORD PTR [SI.FEI_dirsec+2],AX ;AN000;>32mb save high dir sector + MOV AX,[CLUSNUM] ; save next cluster number + MOV [SI.FEI_clusnum],AX + MOV AX,[LASTENT] ;AN000;FO. save lastentry for search first + MOV [SI.FEI_lastent],AX ;AN000;FO. + MOV AX,[DIRSTART] ;AN001;FO. save for search first + MOV [SI.FEI_dirstart],AX ;AN001;FO. + + MOV AX,BX + ADD DI,BUFINSIZ ; DS:DI -> start of data in buffer + SUB AX,DI ; AX=BX relative to start of sector + MOV CL,SIZE dir_entry +;invoke debug_DOS + DIV CL + MOV [SI.FEI_dirpos],AL ; save directory entry # in buffer + + PUSH DS + POP ES + + MOV DS,WORD PTR [CURBUF+2] + MOV DI,BX ; DS:DI -> dir entry info +ASSUME DS:NOTHING + CMP DS:[DI.dir_first],0 ; never insert info when file is empty + JZ SKIP_INSERT ; e.g. newly created file + + PUSH SI ; ES:BX -> extended info + POP BX + + MOV AL,FONC_insert ; call fastopen insert operation + MOV SI,OFFSET DOSGROUP:FastOpenTable + CALL DWORD PTR ES:[SI.FASTOPEN_NAME_CACHING] + + CLC +SKIP_INSERT: + POP AX + POP CX ; restore registers + POP DI + POP SI + POP BX + POP ES + POP DS +GET_NEXT2: + OR [FastOpenFlg],No_Lookup ; we got dir info from fastopen so +GET_NEXT_ELEMENT: + POPF + RET +EndProc InsertPath + +CODE ENDS + END diff --git a/v4.0/src/DOS/DIRCALL.ASM b/v4.0/src/DOS/DIRCALL.ASM new file mode 100644 index 0000000..3c79fe0 --- /dev/null +++ b/v4.0/src/DOS/DIRCALL.ASM @@ -0,0 +1,415 @@ +; SCCSID = @(#)dircall.asm 1.1 85/04/10 +; SCCSID = @(#)dircall.asm 1.1 85/04/10 +TITLE DIRCALL - Directory manipulation internal calls +NAME DIRCALL +; Low level directory manipulation routines for making removing and +; verifying local or NET directories +; +; DOS_MKDIR +; DOS_CHDIR +; DOS_RMDIR +; +; Modification history: +; +; Created: ARR 30 March 1983 +; + +; +; get the appropriate segment definitions +; +.xlist +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +INCLUDE FASTOPEN.INC +INCLUDE FASTXXXX.INC +.cref +.list + +Installed = TRUE + + i_need THISSFT,DWORD + i_need THISCDS,DWORD + i_need NoSetDir,BYTE + i_need CURBUF, DWORD + i_need DIRSTART,WORD + i_need THISDPB,DWORD + i_need NAME1,BYTE + i_need LASTENT,WORD + i_need SATTRIB,BYTE + i_need ATTRIB,BYTE + i_need ALLOWED,BYTE + i_need FAILERR,BYTE + i_need RenBuf,BYTE + i_need FastOpenFlg,BYTE ; DOS 3.3 + i_need FastOpenTable,BYTE ; DOS 3.3 + i_need WFP_START,WORD ; DOS 3.3 + i_need HIGH_SECTOR,WORD ; F.C. >32mb + +BREAK + +; Inputs: +; [WFP_START] Points to WFP string ("d:/" must be first 3 chars, NUL +; terminated) +; [CURR_DIR_END] Points to end of Current dir part of string +; ( = -1 if current dir not involved, else +; Points to first char after last "/" of current dir part) +; [THISCDS] Points to CDS being used +; (Low word = -1 if NUL CDS (Net direct request)) +; Function: +; Make a new directory +; Returns: +; Carry Clear +; No error +; Carry Set +; AX is error code +; error_path_not_found +; Bad path (not in curr dir part if present) +; error_bad_curr_dir +; Bad path in current directory part of path +; error_access_denied +; Already exists, device name +; DS preserved, Others destroyed + + procedure DOS_MKDIR,NEAR + DOSAssume CS,,"DOS_MkDir" + ASSUME ES:NOTHING + + Invoke TestNet + JNC local_mkdir +IF NOT Installed + transfer NET_MKDIR +ELSE + MOV AX,(multNET SHL 8) OR 3 + INT 2FH + return +ENDIF + +NODEACCERRJ: + MOV AX,error_access_denied +BadRet: + STC + LeaveCrit critDisk + return + +PATHNFJ: + LeaveCrit critDisk + transfer SET_MKND_ERR ; Map the MakeNode error and return + +LOCAL_MKDIR: + EnterCrit critDisk +; +; MakeNode requires an SFT to fiddle with. We Use a temp spot (RENBUF) +; + MOV WORD PTR [THISSFT+2],SS + MOV WORD PTR [THISSFT],OFFSET DOSGroup:RenBuf +; +; NOTE: Need WORD PTR because MASM takes type of +; TempSFT (byte) instead of type of sf_mft (word). +; + MOV WORD PTR RenBuf.sf_mft,0 ; make sure SHARER won't complain. + MOV AL,attr_directory + invoke MAKENODE + + JC PATHNFJ + CMP AX,3 + JZ NODEACCERRJ ; Can't make a device into a directory + LES BP,[THISDPB] ; Makenode zaps this + LDS DI,[CURBUF] +ASSUME DS:NOTHING + SUB SI,DI + PUSH SI ; Pointer to dir_first + PUSH WORD PTR [DI.buf_sector+2] ;F.C. >32mb + + PUSH WORD PTR [DI.buf_sector] ; Sector of new node + context DS + PUSH [DIRSTART] ; Parent for .. entry + XOR AX,AX + MOV [DIRSTART],AX ; Null directory + invoke NEWDIR + JC NODEEXISTSPOPDEL ; No room + invoke GETENT ; First entry + JC NODEEXISTSPOPDEL ; Screw up + LES DI,[CURBUF] + + TEST ES:[DI.buf_flags],buf_dirty ;LB. if already dirty ;AN000; + JNZ yesdirty ;LB. don't increment dirty count ;AN000; + invoke INC_DIRTY_COUNT ;LB. ;AN000; + OR ES:[DI.buf_flags],buf_dirty +yesdirty: + ADD DI,BUFINSIZ ; Point at buffer + MOV AX,202EH ; ". " + MOV DX,[DIRSTART] ; Point at itself + invoke SETDOTENT + MOV AX,2E2EH ; ".." + POP DX ; Parent + invoke SETDOTENT + LES BP,[THISDPB] + MOV [ALLOWED],allowed_FAIL + allowed_RETRY + POP DX ; Entry sector + POP [HIGH_SECTOR] ;F.C. >32mb + + XOR AL,AL ; Pre read + invoke GETBUFFR + JC NODEEXISTSP + MOV DX,[DIRSTART] + LDS DI,[CURBUF] +ASSUME DS:NOTHING + OR [DI.buf_flags],buf_isDIR + POP SI ; dir_first pointer + ADD SI,DI + MOV [SI],DX + XOR DX,DX + MOV [SI+2],DX ; Zero size + MOV [SI+4],DX +DIRUP: + TEST [DI.buf_flags],buf_dirty ;LB. if already dirty ;AN000; + JNZ yesdirty2 ;LB. don't increment dirty count ;AN000; + invoke INC_DIRTY_COUNT ;LB. ;AN000; + OR [DI.buf_flags],buf_dirty ; Dirty buffer +yesdirty2: + context DS + MOV AL,ES:[BP.dpb_drive] + invoke FLUSHBUF + MOV AX,error_access_denied + LeaveCrit critDisk + return + +NODEEXISTSPOPDEL: + POP DX ; Parent + POP DX ; Entry sector + POP [HIGH_SECTOR] ; F.C. >32mb + + LES BP,[THISDPB] + MOV [ALLOWED],allowed_FAIL + allowed_RETRY + XOR AL,AL ; Pre read + invoke GETBUFFR + JC NODEEXISTSP + LDS DI,[CURBUF] +ASSUME DS:NOTHING + OR [DI.buf_flags],buf_isDIR + POP SI ; dir_first pointer + ADD SI,DI + SUB SI,dir_first ;Point back to start of dir entry + MOV BYTE PTR [SI],0E5H ; Free the entry + CALL DIRUP ; Error doesn't matter since erroring anyway +NODEEXISTS: + JMP NODEACCERRJ + +NODEEXISTSP: + POP SI ; Clean stack + JMP NODEEXISTS + +EndProc DOS_MKDIR + +BREAK + +; Inputs: +; [WFP_START] Points to WFP string ("d:/" must be first 3 chars, NUL +; terminated) +; [CURR_DIR_END] Points to end of Current dir part of string +; ( = -1 if current dir not involved, else +; Points to first char after last "/" of current dir part) +; [THISCDS] Points to CDS being used May not be NUL +; Function: +; Validate the path for potential new current directory +; Returns: +; NOTE: +; [SATTRIB] is modified by this call +; Carry Clear +; CX is cluster number of the DIR, LOCAL CDS ONLY +; Caller must NOT set ID fields on a NET CDS. +; Carry Set +; AX is error code +; error_path_not_found +; Bad path +; error_access_denied +; device or file name +; DS preserved, Others destroyed + + procedure DOS_CHDIR,NEAR + DOSAssume CS,,"DOS_Chdir" + ASSUME ES:NOTHING + + Invoke TestNet + JNC LOCAL_CHDIR +IF NOT Installed + transfer NET_CHDIR +ELSE + MOV AX,(multNET SHL 8) OR 5 + INT 2FH + return +ENDIF + +LOCAL_CHDIR: + EnterCrit critDisk + TEST ES:[DI.curdir_flags],curdir_splice ;PTM. + JZ nojoin ;PTM. + MOV ES:[DI.curdir_ID],0FFFFH ;PTM. +nojoin: + MOV [NoSetDir],FALSE + MOV [SATTRIB],attr_directory+attr_system+attr_hidden + ; Dir calls can find these +; DOS 3.3 6/24/86 FastOpen + + OR [FastOpenFlg],FastOpen_Set ; set fastopen flag + invoke GetPath + PUSHF ;AN000; + AND [FastOpenFlg],Fast_yes ; clear it all ;AC000; + POPF ;AN000; +; DOS 3.3 6/24/86 FastOpen + MOV AX,error_path_not_found + JC ChDirDone + JNZ NOTDIRPATH ; Path not a DIR + MOV CX,[DIRSTART] ; Get cluster number + CLC +ChDirDone: + LeaveCrit critDisk + return + +EndProc DOS_CHDIR + +BREAK + +; Inputs: +; [WFP_START] Points to WFP string ("d:/" must be first 3 chars, NUL +; terminated) +; [CURR_DIR_END] Points to end of Current dir part of string +; ( = -1 if current dir not involved, else +; Points to first char after last "/" of current dir part) +; [THISCDS] Points to CDS being used +; (Low word = -1 if NUL CDS (Net direct request)) +; Function: +; Remove a directory +; NOTE: Attempt to remove current directory must be detected by caller +; Returns: +; NOTE: +; [SATTRIB] is modified by this call +; Carry Clear +; No error +; Carry Set +; AX is error code +; error_path_not_found +; Bad path (not in curr dir part if present) +; error_bad_curr_dir +; Bad path in current directory part of path +; error_access_denied +; device or file name, root directory +; Bad directory ('.' '..' messed up) +; DS preserved, Others destroyed + + procedure DOS_RMDIR,NEAR + DOSAssume CS,,"DOS_RmDir" + ASSUME ES:NOTHING + + Invoke TestNet + JNC Local_RmDIR +IF NOT Installed + transfer NET_RMDIR +ELSE + MOV AX,(multNET SHL 8) OR 1 + INT 2FH + return +ENDIF + +LOCAL_RMDIR: + EnterCrit critDisk + MOV [NoSetDir],0 + MOV [SATTRIB],attr_directory+attr_system+attr_hidden + ; Dir calls can find these + invoke GetPath + JC NOPATH ; Path not found + JNZ NOTDIRPATH ; Path not a DIR + MOV DI,[DIRSTART] + OR DI,DI ; Root ? + JNZ rmdir_get_buf ; No + JMP SHORT NOTDIRPATH + +NOPATH: + MOV AX,error_path_not_found + JMP BadRet + +NOTDIRPATHPOP: + POP AX ;F.C. >32mb + POP AX +NOTDIRPATHPOP2: + POP AX +NOTDIRPATH: + JMP NodeAccErrJ + +rmdir_get_buf: + LDS DI,[CURBUF] +ASSUME DS:NOTHING + SUB BX,DI ; Compute true offset + PUSH BX ; Save entry pointer + PUSH WORD PTR [DI.buf_sector+2] ;F.C. >32mb + PUSH WORD PTR [DI.buf_sector] ; Save sector number + context DS + context ES + MOV DI,OFFSET DOSGROUP:NAME1 + MOV AL,'?' + MOV CX,11 + REP STOSB + XOR AL,AL + STOSB ; Nul terminate it + invoke STARTSRCH ; Set search + invoke GETENTRY ; Get start of directory + JC NOTDIRPATHPOP ; Screw up + MOV DS,WORD PTR [CURBUF+2] +ASSUME DS:NOTHING + MOV SI,BX + LODSW + CMP AX,(' ' SHL 8) OR '.' ; First entry '.'? + JNZ NOTDIRPATHPOP ; Nope + ADD SI,(SIZE dir_entry) - 2 ; Next entry + LODSW + CMP AX,('.' SHL 8) OR '.' ; Second entry '..'? + JNZ NOTDIRPATHPOP ; Nope + context DS + MOV [LASTENT],2 ; Skip . and .. + invoke GETENTRY ; Get next entry + JC NOTDIRPATHPOP ; Screw up + MOV [ATTRIB],attr_directory+attr_hidden+attr_system + invoke SRCH ; Do a search + JNC NOTDIRPATHPOP ; Found another entry! + CMP [FAILERR],0 + JNZ NOTDIRPATHPOP ; Failure of search due to I 24 FAIL + LES BP,[THISDPB] + MOV BX,[DIRSTART] +;; FastSeek 10/27/86 + invoke Delete_FSeek ; delete the fastseek entry +;; FastSeek 10/27/86 + invoke RELEASE ; Release data in sub dir + JC NOTDIRPATHPOP ; Screw up + POP DX ; Sector # of entry + POP [HIGH_SECTOR] ; F.C. >32mb + + MOV [ALLOWED],allowed_FAIL + allowed_RETRY + XOR AL,AL ; Pre read + invoke GETBUFFR ; Get sector back + JC NOTDIRPATHPOP2 ; Screw up + LDS DI,[CURBUF] +ASSUME DS:NOTHING + OR [DI.buf_flags],buf_isDIR + POP BX ; Pointer to start of entry + ADD BX,DI ; Corrected + MOV BYTE PTR [BX],0E5H ; Free the entry + +;DOS 3.3 FastOpen 6/16/86 F.C. + PUSH DS + context DS + invoke FastOpen_Delete ; call fastopen to delete an entry + POP DS +;DOS 3.3 FastOpen 6/16/86 F.C. + + JMP DIRUP ; In MKDIR, dirty buffer and flush + +EndProc DOS_RMDIR + +CODE ENDS + END diff --git a/v4.0/src/DOS/DISK.ASM b/v4.0/src/DOS/DISK.ASM new file mode 100644 index 0000000..2fad68b --- /dev/null +++ b/v4.0/src/DOS/DISK.ASM @@ -0,0 +1,1073 @@ +; SCCSID = @(#)disk.asm 1.1 85/04/10 +; SCCSID = @(#)disk.asm 1.1 85/04/10 +TITLE DISK - Disk utility routines +NAME Disk +; Low level Read and write routines for local SFT I/O on files and devs +; +; SWAPCON +; SWAPBACK +; DOS_READ +; DOS_WRITE +; get_io_sft +; DirRead +; FIRSTCLUSTER +; SET_BUF_AS_DIR +; FATSecRd +; DREAD +; CHECK_WRITE_LOCK +; CHECK_READ_LOCK +; +; Revision history: +; +; A000 version 4.00 Jan. 1988 +; + +; +; get the appropriate segment definitions +; +.xlist +include dosseg.asm +include fastseek.inc ;AN000; +include fastxxxx.inc ;AN000; + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +include version.inc +.cref +.list + +Installed = TRUE + + I_need DirStart,WORD + I_Need CONSft,DWORD ; SFT for swapped console In/Out + i_need CONSWAP,BYTE + i_need IDLEINT,BYTE + i_need THISSFT,DWORD + i_need DMAADD,DWORD + i_need DEVCALL,BYTE + i_need CALLSCNT,WORD + i_need CALLXAD,DWORD + i_need CONTPOS,WORD + i_need NEXTADD,WORD + i_need CONBUF,BYTE + i_need ClusFac,BYTE + i_need SecClusPos,BYTE + i_need DirSec,DWORD ;AN000; + i_need ClusNum,WORD + i_need NxtClusNum,WORD + i_need ReadOp,BYTE + i_need CURBUF,DWORD + i_need ALLOWED,BYTE + i_need EXTERR_LOCUS,BYTE + i_need FastSeekflg,BYTE ;AN000; + i_need HIGH_SECTOR,WORD ;AN000; + I_need JShare,DWORD ;AN000; + i_need DOS34_FLAG,WORD ;AN000; + +IF BUFFERFLAG + + i_need BUF_EMS_MODE,BYTE + i_need BUF_EMS_LAST_PAGE,BYTE + I_need BUF_EMS_FIRST_PAGE,DWORD + I_need BUF_EMS_SAFE_FLAG,BYTE + I_need BUF_EMS_NPA640,WORD + I_need BUF_EMS_PAGE_FRAME,WORD + I_need BUF_EMS_PFRAME,WORD + I_need LASTBUFFER,DWORD + + extrn save_user_map:near + extrn restore_user_map:near + extrn Setup_EMS_Buffers:near + +ENDIF + +Break +; * * * * Drivers for file input from devices * * * * + +; Indicate that ther is no more I/O occurring through another SFT outside of +; handles 0 and 1 +; +; Inputs: DS is DOSGroup +; Outputs: CONSWAP is set to false. +; Registers modified: none + + procedure SWAPBACK,NEAR + DOSAssume CS,,"SwapBack" + ASSUME ES:NOTHING + MOV BYTE PTR [CONSWAP],0 ; signal no conswaps + return +EndProc SWAPBACK + +; Copy ThisSFT to CONSFT for use by the 1-12 primitives. +; +; Inputs: ThisSFT as the sft of the desired file +; DS is DOSGroup +; Outputs: CONSWAP is set. CONSFT = ThisSFT. +; Registers modified: none + procedure SWAPCON,NEAR + DOSAssume CS,,"SwapCon" + ASSUME ES:NOTHING + SaveReg + MOV BYTE PTR [CONSWAP],1 ; CONSwap = TRUE; + LES DI,ThisSFT + Assert ISSFT,,"SwapCon" + MOV WORD PTR CONSFT,DI + MOV WORD PTR CONSFT+2,ES + RestoreReg + return +EndProc SWAPCON + +Break + +; +; Inputs: +; [THISSFT] set to the SFT for the file being used +; [DMAADD] contains transfer address +; CX = No. of bytes to read +; Function: +; Perform read operation +; Outputs: +; Carry clear +; SFT Position and cluster pointers updated +; CX = No. of bytes read +; ES:DI point to SFT +; Carry set +; AX is error code +; CX = 0 +; ES:DI point to SFT +; DS preserved, all other registers destroyed + + procedure DOS_READ,NEAR + DOSAssume CS,,"DOS_Read" + ASSUME ES:NOTHING + +IF BUFFERFLAG + cmp [BUF_EMS_MODE], -1 + jz dos_rd_call + call choose_buf_page + jnc sav_map_rd_hndl + return +sav_map_rd_hndl: +; call save_user_map +dos_rd_call: +ENDIF + + + LES DI,[THISSFT] + Assert ISSFT,,"DOS_Read" +; +; Verify that the sft has been opened in a mode that allows reading. +; + MOV AL,BYTE PTR ES:[DI.sf_mode] + AND AL,access_mask + CMP AL,open_for_write + JNE READ_NO_MODE ;Is read or both + transfer SET_ACC_ERR + +READ_NO_MODE: + invoke SETUP + JCXZ NoIORet ; no bytes to read - fast return + invoke IsSFTNet + JZ LOCAL_READ + +; invoke OWN_SHARE ;AN000;;IFS. IFS owns share ? +; JZ IFS_HAS_SHARE ;AN000;;IFS. yes +; EnterCrit critDisk ;AN000;;IFS. enter critical section +; CALL CHECK_READ_LOCK ;AN000;;IFS. check read lock +; JNC READ_OK2 ;AN000;;IFS. lock check ok +; JMP SHORT critexit ;AN000;;IFS. fail +READ_OK2: ;AN000; +; LeaveCrit critDisk ;AN000;;IFS. leave critical section +IFS_HAS_SHARE: ;AN000; + +IF NOT Installed + transfer NET_READ +ELSE + MOV AX,(multNET SHL 8) OR 8 + INT 2FH + return +ENDIF + +; +; The user ended up requesting 0 bytes of input. We do nothing for this case +; except return immediately. +; +NoIORet: + CLC + return + +LOCAL_READ: + TEST ES:[DI.sf_flags],devid_device ; Check for named device I/O + JNZ READDEV + MOV [EXTERR_LOCUS],errLOC_Disk + EnterCrit critDisk + TEST [FastSeekflg],Fast_yes ; FastSeek installed ? + JZ FS_no ; no + OR [FastSeekflg],FS_begin ; set fastseek mode +FS_no: + invoke DISKREAD + PUSHF ; save flag + AND CS:[FastSeekflg],FS_end ; reset fastseek mode + POPF ; retore flag +critexit: + LeaveCrit critDisk + return + +; +; We are reading from a device. Examine the status of the device to see if we +; can short-circuit the I/O. If the device in the EOF state or if it is the +; null device, we can safely indicate no transfer. +; +READDEV: + DOSAssume CS,,"DISK/ReadDev" + ASSUME ES:NOTHING + MOV [EXTERR_LOCUS],errLOC_SerDev + MOV BL,BYTE PTR ES:[DI.sf_flags] + LES DI,[DMAADD] + TEST BL,devid_device_EOF ; End of file? + JZ ENDRDDEVJ3 + TEST BL,devid_device_null ; NUL device? + JZ TESTRAW ; NO + XOR AL,AL ; Indicate EOF by setting zero +ENDRDDEVJ3: + JMP ENDRDDEVJ2 + +; +; We need to hit the device. Figure out if we do a raw read or we do the +; bizarre std_con_string_input. +; +TESTRAW: + TEST BL,devid_device_raw ; Raw mode? + JNZ DVRDRAW ; Yes, let the device do all local editing + TEST BL,devid_device_con_in ; Is it console device? + JZ NOTRDCON + JMP READCON + +DVRDRAW: + DOSAssume CS,,"DISK/DvRdRaw" + PUSH ES + POP DS ; Xaddr to DS:DI +ASSUME DS:NOTHING +ReadRawRetry: + MOV BX,DI ; DS:BX transfer addr + XOR AX,AX ; Media Byte, unit = 0 + MOV DX,AX ; Start at 0 + invoke SETREAD + PUSH DS ; Save Seg part of Xaddr + LDS SI,[THISSFT] + Assert ISSFT,,"DOS_Read/DvRdRawR" + invoke DEVIOCALL + MOV DX,DI ; DS:DX is preserved by INT 24 + MOV AH,86H ; Read error + MOV DI,[DEVCALL.REQSTAT] + TEST DI,STERR + JZ CRDROK ; No errors + invoke CHARHARD + MOV DI,DX ; DS:DI is Xaddr + OR AL,AL + JZ CRDROK ; Ignore + CMP AL,3 + JZ CRDFERR ; fail. + POP DS ; Recover saved seg part of Xaddr + JMP ReadRawRetry ; Retry + +; +; We have encountered a device-driver error. We have informed the user of it +; and he has said for us to fail the system call. +; +CRDFERR: + POP DI ; Clean stack +DEVIOFERR: + LES DI,[THISSFT] + Assert ISSFT,,"DOS_Read/DEVIOFERR" + transfer SET_ACC_ERR_DS + +CRDROK: + POP DI ; Chuck saved seg of Xaddr + MOV DI,DX + ADD DI,[CALLSCNT] ; Amount transferred + JMP SHORT ENDRDDEVJ3 + +; We are going to do a cooked read on some character device. There is a +; problem here, what does the data look like? Is it a terminal device, line +; CR line CR line CR, or is it file data, line CR LF line CR LF? Does it have +; a ^Z at the end which is data, or is the ^Z not data? In any event we're +; going to do this: Read in pieces up to CR (CRs included in data) or ^z (^z +; included in data). this "simulates" the way con works in cooked mode +; reading one line at a time. With file data, however, the lines will look +; like, LF line CR. This is a little weird. + +NOTRDCON: + MOV AX,ES + MOV DS,AX +ASSUME DS:NOTHING + MOV BX,DI + XOR DX,DX + MOV AX,DX + PUSH CX + MOV CX,1 + invoke SETREAD + POP CX + LDS SI,[THISSFT] + Assert ISSFT,,"DOS_Read/NotRdCon" + LDS SI,[SI.sf_devptr] +DVRDLP: + invoke DSKSTATCHK + invoke DEVIOCALL2 + PUSH DI ; Save "count" done + MOV AH,86H + MOV DI,[DEVCALL.REQSTAT] + TEST DI,STERR + JZ CRDOK + invoke CHARHARD + POP DI + MOV [CALLSCNT],1 + CMP AL,1 + JZ DVRDLP ;Retry + CMP AL,3 + JZ DEVIOFERR ; FAIL + XOR AL,AL ; Ignore, Pick some random character + JMP SHORT DVRDIGN + +CRDOK: + POP DI + CMP [CALLSCNT],1 + JNZ ENDRDDEVJ2 + PUSH DS + MOV DS,WORD PTR [CALLXAD+2] + MOV AL,BYTE PTR [DI] ; Get the character we just read + POP DS +DVRDIGN: + INC WORD PTR [CALLXAD] ; Next character + MOV [DEVCALL.REQSTAT],0 + INC DI ; Next character + CMP AL,1AH ; ^Z? + JZ ENDRDDEVJ2 ; Yes, done zero set (EOF) + CMP AL,c_CR ; CR? + LOOPNZ DVRDLP ; Loop if no, else done + INC AX ; Resets zero flag so NOT EOF, unless + ; AX=FFFF which is not likely +ENDRDDEVJ2: + JMP SHORT ENDRDDEV + +ASSUME DS:NOTHING,ES:NOTHING + +TRANBUF: + LODSB + STOSB + CMP AL,c_CR ; Check for carriage return + JNZ NORMCH + MOV BYTE PTR [SI],c_LF +NORMCH: + CMP AL,c_LF + LOOPNZ TRANBUF + JNZ ENDRDCON + XOR SI,SI ; Cause a new buffer to be read + invoke OUTT ; Transmit linefeed + OR AL,1 ; Clear zero flag--not end of file +ENDRDCON: + Context DS + CALL SWAPBACK + MOV [CONTPOS],SI +ENDRDDEV: + Context DS + MOV [NEXTADD],DI + JNZ SETSFTC ; Zero set if Ctrl-Z found in input + LES DI,[THISSFT] + Assert ISSFT,,"DOS_Read/EndRdDev" + AND BYTE PTR ES:[DI.sf_flags],NOT devid_device_EOF ; Mark as no more data available +SETSFTC: + invoke SETSFT + return + +ASSUME DS:NOTHING,ES:NOTHING + +READCON: + DOSAssume CS,,"ReadCon" + CALL SWAPCON + MOV SI,[CONTPOS] + OR SI,SI + JNZ TRANBUF + CMP BYTE PTR [CONBUF],128 + JZ GETBUF + MOV WORD PTR [CONBUF],0FF80H ; Set up 128-byte buffer with no template +GETBUF: + PUSH CX + PUSH ES + PUSH DI + MOV DX,OFFSET DOSGROUP:CONBUF + invoke $STD_CON_STRING_INPUT ; Get input buffer + POP DI + POP ES + POP CX + MOV SI,2 + OFFSET DOSGROUP:CONBUF + CMP BYTE PTR [SI],1AH ; Check for Ctrl-Z in first character + JNZ TRANBUF + MOV AL,1AH + STOSB + DEC DI + MOV AL,c_LF + invoke OUTT ; Send linefeed + XOR SI,SI + JMP ENDRDCON + +EndProc DOS_READ + +Break + +; +; Inputs: +; [THISSFT] set to the SFT for the file being used +; [DMAADD] contains transfer address +; CX = No. of bytes to write +; Function: +; Perform write operation +; NOTE: If CX = 0 on input, file is truncated or grown +; to current sf_position +; Outputs: +; Carry clear +; SFT Position and cluster pointers updated +; CX = No. of bytes written +; ES:DI point to SFT +; Carry set +; AX is error code +; CX = 0 +; ES:DI point to SFT +; DS preserved, all other registers destroyed + + procedure DOS_WRITE,NEAR + DOSAssume CS,,"DOS_Write" + ASSUME ES:NOTHING + +IF BUFFERFLAG + cmp [BUF_EMS_MODE], -1 + jz dos_wrt_call + call choose_buf_page + jnc sav_map_wrt_hndl + return +sav_map_wrt_hndl: +; call save_user_map +dos_wrt_call: +ENDIF + + + LES DI,[THISSFT] + Assert ISSFT,,"DosWrite" + MOV AL,BYTE PTR ES:[DI.sf_mode] + AND AL,access_mask + CMP AL,open_for_read + JNE Check_FCB_RO ;Is write or both +BadMode: + transfer SET_ACC_ERR + +; +; NOTE: The following check for writting to a Read Only File is performed +; ONLY on FCBs!!!! +; We ALLOW writes to Read Only files via handles to allow a CREATE +; of a read only file which can then be written to. +; This is OK because we are NOT ALLOWED to OPEN a RO file via handles +; for writting, or RE-CREATE an EXISTING RO file via handles. Thus, +; CREATing a NEW RO file, or RE-CREATing an existing file which +; is NOT RO to be RO, via handles are the only times we can write +; to a read-only file. +; +Check_FCB_RO: + TEST ES:[DI.sf_mode],sf_isfcb + JZ WRITE_NO_MODE ; Not an FCB + TEST ES:[DI].sf_attr,attr_read_only + JNZ BadMode ; Can't write to Read_Only files via FCB +WRITE_NO_MODE: + invoke SETUP + invoke IsSFTNet + JZ LOCAL_WRITE + +; invoke OWN_SHARE ;AN000;;IFS. IFS owns share ? +; JZ IFS_HAS_SHARE2 ;AN000;;IFS. yes +; EnterCrit critDisk ;AN000;;IFS. enter critical section +; CALL CHECK_WRITE_LOCK ;AN000;;IFS. check write lock +; JC nocommit ;AN000;;IFS. lock error +; +; LeaveCrit critDisk ;AN000;;IFS. leave critical section +IFS_HAS_SHARE2: ;AN000; + + +IF NOT Installed + transfer NET_WRITE +ELSE + MOV AX,(multNET SHL 8) OR 9 + INT 2FH +; JC nomore ;AN000;;IFS. error +; invoke OWN_SHARE ;AN000;;IFS. IFS owns share ? +; JZ nomore ;AN000;;IFS. yes +; +; MOV AX,1 ;AN000;;IFS. update all SFT for new size +; call JShare + 14 * 4 ;AN000;;IFS. call ShSu + +nomore: ;AN000; + return +ENDIF + + +LOCAL_WRITE: + TEST ES:[DI.sf_flags],devid_device ; Check for named device I/O + JNZ WRTDEV + MOV [EXTERR_LOCUS],errLOC_Disk + EnterCrit critDisk + TEST [FastSeekflg],Fast_yes ;AN000;FO. FastSeek installed ? + JZ FS_no2 ;AN000;FO. no + OR [FastSeekflg],FS_begin ;AN000;FO. set fastseek mode +FS_no2: ;AN000; + invoke DISKWRITE + PUSHF ;AN000;FO. save flag + AND CS:[FastSeekflg],FS_end ;AN000;FO. reset fastseek mode + POPF ;AN000;FO. restore flag +;; Extended Open + JC nocommit ;AN000;EO. + LES DI,[THISSFT] ;AN000;EO. + TEST ES:[DI.sf_mode],auto_commit_write ;AN000;EO. + JZ nocommit ;AN000;EO. + PUSH CX ;AN000;EO. + invoke DOS_COMMIT ;AN000;EO. + POP CX ;AN000;EO. +nocommit: ;AN000; +;; Extended Open + LeaveCrit critDisk + return + +DVWRTRAW: +ASSUME DS:NOTHING + XOR AX,AX ; Media Byte, unit = 0 + invoke SETWRITE + PUSH DS ; Save seg of transfer + LDS SI,[THISSFT] + Assert ISSFT,,"DosWrite/DvWrtRaw" + invoke DEVIOCALL ; DS:SI -> DEVICE + MOV DX,DI ; Offset part of Xaddr saved in DX + MOV AH,87H + MOV DI,[DEVCALL.REQSTAT] + TEST DI,STERR + JZ CWRTROK + invoke CHARHARD + MOV BX,DX ; Recall transfer addr + OR AL,AL + JZ CWRTROK ; Ignore + CMP AL,3 + JZ CWRFERR + POP DS ; Recover saved seg of transfer + JMP DVWRTRAW ; Try again + +CWRFERR: + POP AX ; Chuck saved seg of transfer + JMP CRDFERR ; Will pop one more stack element + +CWRTROK: + POP AX ; Chuck saved seg of transfer + POP DS + DOSAssume CS,,"DISK/CWrtOK" + MOV AX,[CALLSCNT] ; Get actual number of bytes transferred +ENDWRDEV: + LES DI,[THISSFT] + Assert ISSFT,,"DosWrite/EndWrDev" + MOV CX,AX + invoke ADDREC + return + +WRTNUL: + MOV DX,CX ;Entire transfer done +WrtCookJ: + JMP WRTCOOKDONE + +WRTDEV: + DOSAssume CS,,"DISK/WrtDev" + MOV [EXTERR_LOCUS],errLOC_SerDev + OR BYTE PTR ES:[DI.sf_flags],devid_device_EOF ; Reset EOF for input + MOV BL,BYTE PTR ES:[DI.sf_flags] + XOR AX,AX + JCXZ ENDWRDEV ; problem of creating on a device. + PUSH DS + MOV AL,BL + LDS BX,[DMAADD] ; Xaddr to DS:BX +ASSUME DS:NOTHING + MOV DI,BX ; Xaddr to DS:DI + XOR DX,DX ; Set starting point + TEST AL,devid_device_raw ; Raw? + JZ TEST_DEV_CON + JMP DVWRTRAW + +TEST_DEV_CON: + TEST AL,devid_device_con_out ; Console output device? + JNZ WRITECON + TEST AL,devid_device_null + JNZ WRTNUL + MOV AX,DX + CMP BYTE PTR [BX],1AH ; ^Z? + JZ WRTCOOKJ ; Yes, transfer nothing + PUSH CX + MOV CX,1 + invoke SETWRITE + POP CX + LDS SI,[THISSFT] + OR CS:[DOS34_FLAG],X25_Special;AN000;;PTM. bad x25 driver + MOV AH,3 ;AN000;;PTM. prompt critical error ASAP + invoke IOFUNC ;AN000;;PTM. + Assert ISSFT,,"DosWrite/TestDevCon" + LDS SI,[SI.sf_devptr] +DVWRTLP: + invoke DSKSTATCHK + invoke DEVIOCALL2 + PUSH DI + MOV AH,87H + MOV DI,[DEVCALL.REQSTAT] + TEST DI,STERR + JZ CWROK + invoke CHARHARD + POP DI + MOV [CALLSCNT],1 + CMP AL,1 + JZ DVWRTLP ; Retry + OR AL,AL + JZ DVWRTIGN ; Ignore + JMP CRDFERR ; Fail, pops one stack element + +CWROK: + POP DI + CMP [CALLSCNT],0 + JZ WRTCOOKDONE +DVWRTIGN: + INC DX + INC WORD PTR [CALLXAD] + INC DI + PUSH DS + MOV DS,WORD PTR [CALLXAD+2] + CMP BYTE PTR [DI],1AH ; ^Z? + POP DS + JZ WRTCOOKDONE + MOV [DEVCALL.REQSTAT],0 + LOOP DVWRTLP +WRTCOOKDONE: + MOV AX,DX + POP DS + JMP ENDWRDEV + +WRITECON: + PUSH DS + Context DS + CALL SWAPCON + POP DS +ASSUME DS:NOTHING + MOV SI,BX + PUSH CX +WRCONLP: + LODSB + CMP AL,1AH ; ^Z? + JZ CONEOF + invoke OUTT + LOOP WRCONLP +CONEOF: + POP AX ; Count + SUB AX,CX ; Amount actually written + POP DS + DOSAssume CS,,"DISK/ConEOF" + CALL SWAPBACK + JMP ENDWRDEV +EndProc DOS_WRITE + +; Convert JFN number in BX to sf_entry in DS:SI We get the normal SFT if +; CONSWAP is FALSE or if the handle desired is 2 or more. Otherwise, we +; retrieve the sft from ConSFT which is set by SwapCon. + + procedure get_io_sft,near +ASSUME DS:NOTHING,ES:NOTHING + TEST ConSwap,-1 + JNZ GetRedir +GetNormal: + Context DS + PUSH ES + PUSH DI + invoke SFFromHandle + JC RET44P + MOV SI,ES + MOV DS,SI +ASSUME DS:NOTHING + MOV SI,DI +RET44P: + POP DI + POP ES + return +GetRedir: + CMP BX,1 + JA GetNormal + LDS SI,ConSFT + Assert ISSFT,,"GetIOSft" + CLC + return +EndProc get_io_sft + +Break + +; Inputs: +; AX = Directory block number (relative to first block of directory) +; ES:BP = Base of drive parameters +; [DIRSEC] = First sector of first cluster of directory +; [CLUSNUM] = Next cluster +; [CLUSFAC] = Sectors/Cluster +; Function: +; Read the directory block into [CURBUF]. +; Outputs: +; [NXTCLUSNUM] = Next cluster (after the one skipped to) +; [SECCLUSPOS] Set +; ES:BP unchanged +; [CURBUF] Points to Buffer with dir sector +; Carry set if error (user said FAIL to I 24) +; DS preserved, all other registers destroyed. + + procedure DirRead,NEAR + DOSAssume CS,,"DirRead" + ASSUME ES:NOTHING + Assert ISDPB,,"DirRead" + +; +; Note that ClusFac is is the sectors per cluster. This is NOT necessarily +; the same as what is in the DPB! In the case of the root directory, we have +; ClusFac = # sectors in the root directory. The root directory is detected +; by DIRStart = 0. +; + XOR DX,DX + CMP DirStart,0 + jnz SubDir + XCHG AX,DX + JMP DoRead +; +; Convert the sector number in AX into cluster and sector-within-cluster pair +; +SubDir: + MOV DL,AL + AND DL,ES:[BP.dpb_cluster_mask] +; +; DX is the sector-in-cluster +; + MOV CL,ES:[BP.dpb_cluster_shift] + SHR AX,CL +; +; DX is position in cluster +; AX is number of clusters to skip +; +DoRead: + MOV [SECCLUSPOS],DL + MOV CX,AX + MOV AH,DL +; +; CX is number of clusters to skip. +; AH is remainder +; + MOV DX,WORD PTR [DIRSEC+2] ;AN000;>32mb + MOV [HIGH_SECTOR],DX ;AN000;>32mb + MOV DX,WORD PTR [DIRSEC] + ADD DL,AH + ADC DH,0 + ADC [HIGH_SECTOR],0 ;AN000;>32mb + + MOV BX,[CLUSNUM] + MOV [NXTCLUSNUM],BX + JCXZ FIRSTCLUSTER +SKPCLLP: + invoke UNPACK + retc + XCHG BX,DI + invoke IsEOF ; test for eof based on fat size + JAE HAVESKIPPED + LOOP SKPCLLP +HAVESKIPPED: + MOV [NXTCLUSNUM],BX + MOV DX,DI + MOV BL,AH + invoke FIGREC + + entry FIRSTCLUSTER + + MOV [ALLOWED],allowed_RETRY + allowed_FAIL + XOR AL,AL ; Indicate pre-read + invoke GETBUFFR + retc + + entry SET_BUF_AS_DIR + DOSAssume CS,,"SET_BUF_AS_DIR" + ASSUME ES:NOTHING +; Set the type of CURBUF to be a directory sector. +; Only flags are modified. + + PUSH DS + PUSH SI + LDS SI,[CURBUF] + Assert ISBUF,,"SetBufAsDir" + OR [SI.buf_flags],buf_isDIR ; Clears carry + POP SI + POP DS + return +EndProc DirRead + +Break + +; Inputs: +; Same as DREAD +; DS:BX = Transfer address +; CX = Number of sectors +; DX = Absolute record number +; ES:BP = Base of drive parameters +; Function: +; Calls BIOS to perform FAT read. +; Outputs: +; Same as DREAD + + procedure FATSecRd,NEAR +ASSUME DS:NOTHING,ES:NOTHING + + Assert ISDPB,,"FATSecRd" + MOV [ALLOWED],allowed_RETRY + allowed_FAIL + MOV DI,CX + MOV CL,ES:[BP.dpb_FAT_count] + MOV AX,ES:[BP.dpb_FAT_size] ;AN000;>32mb +; XOR AH,AH + XOR CH,CH ;AN000;>32mb + PUSH DX +NXTFAT: + MOV [HIGH_SECTOR],0 ;AN000;>32mb FAT sectors cannot exceed + PUSH CX ;AN000;>32mb + PUSH AX + MOV CX,DI + invoke DSKREAD + POP AX + POP CX + JZ RET41P ; Carry clear + ADD DX,AX + LOOP NXTFAT + POP DX + MOV CX,DI + +; NOTE FALL THROUGH + +Break + +; Inputs: +; DS:BX = Transfer address +; CX = Number of sectors +; DX = Absolute record number (LOW) +; [HIGH_SECTOR]= Absolute record number (HIGH) +; ES:BP = Base of drive parameters +; [ALLOWED] must be set in case call to HARDERR needed +; Function: +; Calls BIOS to perform disk read. If BIOS reports +; errors, will call HARDERRRW for further action. +; Outputs: +; Carry set if error (currently user FAILED to INT 24) +; DS,ES:BP preserved. All other registers destroyed. + + entry DREAD +ASSUME DS:NOTHING,ES:NOTHING + + Assert ISDPB,,"DREAD" + invoke DSKREAD + retz ; Carry clear + MOV BYTE PTR [READOP],0 + invoke HARDERRRW + CMP AL,1 ; Check for retry + JZ DREAD + CMP AL,3 ; Check for FAIL + CLC + JNZ NO_CAR ; Ignore + STC +NO_CAR: + return + +RET41P: POP DX + return +EndProc FATSecRd + + +Break + +; Inputs: +; output of SETUP +; ES:DI -> SFT +; Function: +; check write lock +; Outputs: +; Carry set if error +; Carry clear if ok + + procedure CHECK_WRITE_LOCK,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + + TEST ES:[DI].sf_attr,attr_volume_id ;AN000;;MS. volume id + JZ write_cont ;AN000;;MS. no + invoke SET_ACC_ERR_DS ;AN000;;MS. + return ;AN000;;MS. +write_cont: ;AN000; + PUSH CX ;AN000;;MS. save reg + OR CX,CX ;AN000;;MS. + JNZ Not_Truncate ;AN000;;MS. + MOV CX,0FFFFH ;AN000;;MS. check for lock on whole file +Not_Truncate: ;AN000; + MOV AL,80H ;AN000;;MS. check write access + invoke LOCK_CHECK ;AN000;;MS. check lock + POP CX ;AN000;;MS. restore reg + JNC WRITE_OK ;AN000;;MS. lock ok + invoke WRITE_LOCK_VIOLATION ;AN000;;MS. issue I24 + JNC CHECK_WRITE_LOCK ;AN000;;MS. retry +WRITE_OK: ;AN000; + return ;AN000;;MS. +EndProc CHECK_WRITE_LOCK ;AN000; + + +Break + +; Inputs: +; ES:DI -> SFT +; output of SETUP +; Function: +; check read lock +; Outputs: +; Carry set if error +; Carry clear if ok + + procedure CHECK_READ_LOCK,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + + TEST ES:[DI].sf_attr,attr_volume_id ;AN000;;MS. volume id + JZ do_retry ;AN000;;MS. no + invoke SET_ACC_ERR ;AN000;;MS. + return ;AN000;;MS. +do_retry: ;AN000; + MOV AL,0 ;AN000;;MS. check read access + invoke LOCK_CHECK ;AN000;;MS. check lock + JNC READ_OK ;AN000;;MS. lock ok + invoke READ_LOCK_VIOLATION ;AN000;;MS. issue I24 + JNC CHECK_READ_LOCK ;AN000;;MS. retry +READ_OK: ;AN000; MS. + return ;AN000;;MS. +EndProc CHECK_READ_LOCK ;AN000; + +IF BUFFERFLAG + +;------------------------------------------------------------------------- +; Function name : choose_buf_page +; Inputs : DMAADD = Xaddr +; cx = # of bytes to transfer +; Outputs : if NC +; +; SAFE_FLAG - 0 ==> page is safe. no need to +; detect collision between +; user & system buffer. +; SAFE_FLAG - 1 ==> page is unsafe. Must check +; for collision +; +; CY - error +; +; +; High Level Alogrithm: +; +; 1. If Xaddr. is above the first physical page above 640K +; 2. choose that page +; 3. set safe flag +; 4. else +; 5. choose highest page above 640K +; 6. If 6 or more pages above 640k +; 7. Set safe flag +; 8. else +; 9. if Xaddr. + # of bytes to transfer does not spill into the +; chosen page +; 10. set safe flag +; 11.else +; 12. clear safe flag +; 13.endif +; 14.endif +; 15.endif +; +;---------------------------------------------------------------------------- +Procedure choose_buf_page,near + + assume cs:dosgroup, ds:nothing, es:nothing, ss:dosgroup + + push cx + push bx + push dx + push si + push ds + push ax + + mov ax, word ptr [DMAADD+2] + and ax, 0fc00h ; page segment of transfer segment + + cmp ax, word ptr [BUF_EMS_FIRST_PAGE] + ja pick_first + + cmp [BUF_EMS_NPA640], 6 + jae safe_pick_last + + add cx, word ptr [DMAADD] ; get final offset + mov bx, cx + + mov cl, 4 + shr bx, cl ; get # of paragraphs + mov ax, word ptr [DMAADD+2] ; get initial segment + add ax, bx ; get final segment + + and ax, 0fc00h + cmp ax, word ptr [BUF_EMS_LAST_PAGE] + jne safe_pick_last + + mov [BUF_EMS_SAFE_FLAG], 0 + jmp fin_choose_page + +safe_pick_last: + mov [BUF_EMS_SAFE_FLAG], 1 + jmp fin_choose_page + +;pick_last: +; mov ax, word ptr [BUF_EMS_LAST_PAGE] +; mov [BUF_EMS_PFRAME], ax +; mov ax, word ptr [BUF_EMS_LAST_PAGE+2] +; mov [BUF_EMS_PAGE_FRAME], ax +; xor ax, ax +; jmp fin_choose_page + +pick_first: + mov ax, word ptr [BUF_EMS_FIRST_PAGE] + cmp [BUF_EMS_PFRAME], ax + je fin_choose_page + call restore_user_map + mov word ptr [LASTBUFFER], -1 + mov [BUF_EMS_PFRAME], ax + mov ax, word ptr [BUF_EMS_FIRST_PAGE+2] + mov [BUF_EMS_PAGE_FRAME], ax + mov [BUF_EMS_SAFE_FLAG], 1 + call Setup_EMS_Buffers + call save_user_map + jmp fin_choose_page + +err_choose_page: + stc + +fin_choose_page: + clc + + pop ax + pop ds + pop si + pop dx + pop bx + pop cx + return + +EndProc choose_buf_page + +ENDIF + +CODE ENDS + END + + diff --git a/v4.0/src/DOS/DISK2.ASM b/v4.0/src/DOS/DISK2.ASM new file mode 100644 index 0000000..bb76e89 --- /dev/null +++ b/v4.0/src/DOS/DISK2.ASM @@ -0,0 +1,784 @@ +; SCCSID = @(#)disk2.asm 1.3 85/06/19 +; SCCSID = @(#)disk2.asm 1.3 85/06/19 +TITLE DISK2 - Disk utility routines +NAME Disk2 +; Low level Read and write routines for local SFT I/O on files and devs +; +; DskRead +; DWRITE +; DSKWRITE +; HarderrRW +; SETUP +; BREAKDOWN +; READ_LOCK_VIOLATION +; WRITE_LOCK_VIOLATION +; DISKREAD +; SET_ACC_ERR_DS +; SET_ACC_ERR +; SETSFT +; SETCLUS +; AddRec +; +; Revision history: +; +; AN000 version 4.00 Jan. 1988 +; + +; +; get the appropriate segment definitions +; +.xlist +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +include version.inc +.cref +.list + +Installed = TRUE + + i_need THISSFT,DWORD + i_need DMAADD,DWORD + i_need NEXTADD,WORD + i_need ThisDrv,BYTE + i_need SecClusPos,BYTE + i_need ClusNum,WORD + i_need ReadOp,BYTE + i_need Trans,BYTE + i_need BytPos,4 + i_need SecPos,DWORD ; DOS 4.00 >32mb ;AN000; + i_need BytSecPos,WORD + i_need BytCnt1,WORD + i_need BytCnt2,WORD + i_need SecCnt,WORD + i_need ThisDPB,DWORD + i_need LastPos,WORD + i_need EXTERRPT,DWORD + i_need CALLVIDRW,DWORD + i_need ALLOWED,BYTE + i_need DEVCALL,BYTE + i_need CALLSCNT,WORD + i_need DISK_FULL,BYTE ; disk full flag for ran blk wrt + i_need FSeek_drive,BYTE ; DOS 4.00 ;AN000; + i_need FSeek_firclus,WORD ; DOS 4.00 ;AN000; + i_need HIGH_SECTOR,WORD ; F.C. >32mb ;AN000; + i_need TEMP_VAR2,WORD ; LB. ;AN000; + i_need TEMP_VAR,WORD ; LB. ;AN000; + i_need IFS_DRIVER_ERR,WORD ; LB. ;AN000; + i_need CurHashEntry,DWORD ; DOS 4.00 current Hash entry ;AN000; + i_need BUF_HASH_PTR,DWORD ; DOS 4.00 Hash table pointer ;AN000; + i_need BUF_HASH_COUNT,WORD ; DOS 4.00 Hash table entries ;AN000; + i_need LastBuffer,DWORD + i_need FIRST_BUFF_ADDR,WORD ; first buffer address ;AN000; + +IF BUFFERFLAG + EXTRN SAVE_MAP:NEAR + EXTRN RESTORE_MAP:NEAR + EXTRN SAVE_USER_MAP:NEAR + EXTRN RESTORE_USER_MAP:NEAR + i_need BUF_EMS_SAFE_FLAG,BYTE + i_need BUF_EMS_MODE,BYTE + i_need CURADD,WORD +ENDIF + + +Break + +; Inputs: +; DS:BX = Transfer addr +; CX = Number of sectors +; [HIGH_SECTOR] = Absolute record number (HIGH) +; DX = Absolute record number (LOW) +; ES:BP = Base of drive parameters +; Function: +; Call BIOS to perform disk read +; Outputs: +; DI = CX on entry +; CX = Number of sectors unsuccessfully transfered +; AX = Status word as returned by BIOS (error code in AL if error) +; Zero set if OK (from BIOS) (carry clear) +; Zero clear if error (carry clear) +; SI Destroyed, others preserved + + procedure DskRead,NEAR +ASSUME DS:NOTHING,ES:NOTHING + + Assert ISDPB,,"DskRead" + PUSH CX + MOV AH,ES:[BP.dpb_media] + MOV AL,ES:[BP.dpb_UNIT] + PUSH BX + PUSH ES + invoke SETREAD + JMP DODSKOP + +Break + +; Inputs: +; DS:BX = Transfer address +; CX = Number of sectors +; [HIGH_SECTOR] = Absolute record number (HIGH) +; DX = Absolute record number (LOW) +; ES:BP = Base of drive parameters +; [ALLOWED] must be set in case HARDERR called +; Function: +; Calls BIOS to perform disk write. If BIOS reports +; errors, will call HARDERRRW for further action. +; Output: +; Carry set if error (currently, user FAILed to I 24) +; BP preserved. All other registers destroyed. + + entry DWRITE +ASSUME DS:NOTHING,ES:NOTHING + + Assert ISDPB,,"DWrite" + CALL DSKWRITE + retz ; Carry clear + MOV BYTE PTR [READOP],1 + invoke HARDERRRW + CMP AL,1 ; Check for retry + JZ DWRITE + CMP AL,3 ; Check for FAIL + CLC + JNZ NO_CAR2 ; Ignore + STC +NO_CAR2: + return + +Break + +; Inputs: +; DS:BX = Transfer addr +; CX = Number of sectors +; DX = Absolute record number (LOW) +; [HIGH_SECTOR] = Absolute record number (HIGH) +; ES:BP = Base of drive parameters +; Function: +; Call BIOS to perform disk read +; Outputs: +; DI = CX on entry +; CX = Number of sectors unsuccessfully transfered +; AX = Status word as returned by BIOS (error code in AL if error) +; Zero set if OK (from BIOS) (carry clear) +; Zero clear if error (carry clear) +; SI Destroyed, others preserved + + entry DSKWRITE +ASSUME DS:NOTHING,ES:NOTHING + + Assert ISDPB,,"DskWrite" + PUSH CX + MOV AH,ES:[BP.dpb_media] + MOV AL,ES:[BP.dpb_UNIT] + PUSH BX + PUSH ES + invoke SETWRITE +DODSKOP: + MOV CX,DS ; Save DS + POP DS ; DS:BP points to DPB + PUSH DS + LDS SI,DS:[BP.dpb_driver_addr] + invoke DEVIOCALL2 + MOV DS,CX ; Restore DS + POP ES ; Restore ES + POP BX + MOV CX,[CALLSCNT] ; Number of sectors transferred + POP DI + SUB CX,DI + NEG CX ; Number of sectors not transferred + MOV AX,[DEVCALL.REQSTAT] + MOV [IFS_DRIVER_ERR],AX ;IFS. save it for IFS ;AN000; + TEST AX,STERR + return +EndProc DskRead + + + +Break + +; Inputs: +; AX is error code from read or write +; Other registers set as per HARDERR +; Function: +; Checks the error code for special extended +; errors and maps them if needed. Then invokes +; Harderr +; Outputs: +; Of HARDERR +; AX may be modified prior to call to HARDERR. +; No other registers altered. + + procedure HARDERRRW,near +ASSUME DS:NOTHING,ES:NOTHING + + CMP AL,error_I24_wrong_disk + JNZ DO_ERR ; Nothing to do + PUSH DS + PUSH SI + LDS SI,[CALLVIDRW] ; Get pointer from dev + MOV WORD PTR [EXTERRPT+2],DS ; Set ext err pointer + MOV WORD PTR [EXTERRPT],SI + POP SI + POP DS +DO_ERR: + invoke HARDERR + return + +EndProc HARDERRRW + +Break + +; Inputs: +; ES:DI point to SFT (value also in THISSFT) +; [DMAADD] contains transfer address +; CX = Byte count +; WARNING Stack must be clean, two ret addrs on stack, 1st of caller, +; 2nd of caller of caller. +; Outputs: +; CX = byte count +; [THISDPB] = Base of drive parameters if file +; = Pointer to device header if device or NET +; ES:DI Points to SFT +; [NEXTADD] = Displacement of disk transfer within segment +; [TRANS] = 0 (No transfers yet) +; [BYTPOS] = Byte position in file +; +; The following fields are relevant to local files (not devices) only: +; +; [SECPOS] = Position of first sector (local files only) +; [BYTSECPOS] = Byte position in first sector (local files only) +; [CLUSNUM] = First cluster (local files only) +; [SECCLUSPOS] = Sector within first cluster (local files only) +; [THISDRV] = Physical unit number (local files only) +; +; RETURNS ONE LEVEL UP WITH: +; CX = 0 +; CARRY = Clear +; IF AN ERROR IS DETECTED +; All other registers destroyed + + procedure SETUP,NEAR + DOSAssume CS,,"SetUp" + ASSUME ES:NOTHING + + Assert ISSFT,,"SetUp" + LDS SI,ES:[DI.sf_devptr] +ASSUME DS:NOTHING + MOV WORD PTR [THISDPB+2],DS + context DS + MOV WORD PTR [THISDPB],SI + MOV BX,WORD PTR [DMAADD] + MOV [NEXTADD],BX ;Set NEXTADD to start of Xaddr + MOV BYTE PTR [TRANS],0 ;No transferes + MOV AX,WORD PTR ES:[DI.sf_Position] + MOV DX,WORD PTR ES:[DI.sf_Position+2] + MOV WORD PTR [BYTPOS+2],DX ;Set it + MOV WORD PTR [BYTPOS],AX + TEST ES:[DI.sf_flags],sf_isnet + devid_device + JNZ NOSETSTUFF ;Following not done on devs or NET + PUSH ES + LES BP,[THISDPB] ;Point at the DPB + Assert ISDPB,,"Setup" + MOV BL,ES:[BP.dpb_drive] + MOV [THISDRV],BL ;Set THISDRV + MOV BX,ES:[BP.dpb_sector_size] +; CMP DX,BX ; See if divide will overflow +; JNC EOFERR ; for 16 bit sector +;; 32 bit divide + invoke DIV32 ; F.C. >32mb ;AN000; + MOV WORD PTR [SECPOS],AX ; F.C. >32mb ;AN000; + MOV BX,[HIGH_SECTOR] ; F.C. >32mb ;AN000; + MOV WORD PTR [SECPOS+2],BX ; F.C. >32mb ;AN000; + + MOV [BYTSECPOS],DX + MOV DX,AX + AND AL,ES:[BP.dpb_cluster_mask] + MOV [SECCLUSPOS],AL + MOV AX,CX ; Save byte count +; MOV CL,ES:[BP.dpb_cluster_shift] + PUSH WORD PTR [SECPOS+2] ; F.C. >32mb ;AN000; + POP [HIGH_SECTOR] ; F.C. >32mb ;AN000; + PUSH AX ; F.C. >32mb save ax ;AN000; + MOV AX,DX ; F.C. >32mb ax=dx ;AN000; + invoke SHR32 ; F.C. >32mb shift ax ;AN000; + MOV DX,AX ; F.C. >32mb dx=ax ;AN000; + POP AX ; F.C. >32mb restore dx ;AN000; + +; SHR DX,CL + CMP DX,ES:[BP.dpb_max_cluster] ;>32mb if > disk size ;AN000; ;AN000; + JA EOFERR ;>32mb then EOF ;AN000; ;AN000; + + MOV [CLUSNUM],DX + POP ES ; ES:DI point to SFT + MOV CX,AX ; Put byte count back in CX +NOSETSTUFF: + MOV AX,CX ; Need it in AX too + ADD AX,WORD PTR [DMAADD] ; See if it will fit in one segment + JNC OK ; Must be less than 64K + MOV AX,WORD PTR [DMAADD] + NEG AX ; Amount of room left in segment (know + ; less than 64K since max value of CX + ; is FFFF). + JNZ NoDec + DEC AX +NoDec: + MOV CX,AX ; Can do this much + JCXZ NOROOM ; Silly user gave Xaddr of FFFF in segment +OK: + return + +EOFERR: + POP ES ; ES:DI point to SFT + XOR CX,CX ; No bytes read +;;;;;;;;;;; 7/18/86 +; MOV BYTE PTR [DISK_FULL],1 ; set disk full flag +;;;;;;;;;;; +NOROOM: + POP BX ; Kill return address + CLC + return ; RETURN TO CALLER OF CALLER +EndProc SETUP + +Break + +; Inputs: +; CX = Length of disk transfer in bytes +; ES:BP = Base of drive parameters +; [BYTSECPOS] = Byte position witin first sector +; Outputs: +; [BYTCNT1] = Bytes to transfer in first sector +; [SECCNT] = No. of whole sectors to transfer +; [BYTCNT2] = Bytes to transfer in last sector +; AX, BX, DX destroyed. No other registers affected. + + procedure BREAKDOWN,near + DOSAssume CS,,"BreakDown" + ASSUME ES:NOTHING + + Assert ISDPB,,"BreakDown" + MOV AX,[BYTSECPOS] + MOV BX,CX + OR AX,AX + JZ SAVFIR ; Partial first sector? + SUB AX,ES:[BP.dpb_sector_size] + NEG AX ; Max number of bytes left in first sector + SUB BX,AX ; Subtract from total length + JAE SAVFIR + ADD AX,BX ; Don't use all of the rest of the sector + XOR BX,BX ; And no bytes are left +SAVFIR: + MOV [BYTCNT1],AX + MOV AX,BX + XOR DX,DX + DIV ES:[BP.dpb_sector_size] ; How many whole sectors? + MOV [SECCNT],AX + MOV [BYTCNT2],DX ; Bytes remaining for last sector + OR DX,[BYTCNT1] + retnz ; NOT (BYTCNT1 = BYTCNT2 = 0) + CMP AX,1 + retnz + MOV AX,ES:[BP.dpb_sector_size] ; Buffer EXACT one sector I/O + MOV [BYTCNT2],AX + MOV [SECCNT],DX ; DX = 0 +RET45: + return +EndProc BreakDown + +; ES:DI points to SFT. This entry used by NET_READ +; Carry set if to return error (CX=0,AX=error_sharing_violation). +; Else do retrys. +; ES:DI,DS,CX preserved + + procedure READ_LOCK_VIOLATION,NEAR + DOSAssume CS,,"Read_Lock_Violation" + ASSUME ES:NOTHING + + Assert ISSFT,,"ReadLockViolation" + + MOV [READOP],0 +ERR_ON_CHECK: + TEST ES:[DI.sf_mode],sf_isfcb + JNZ HARD_ERR + PUSH CX + MOV CL,BYTE PTR ES:[DI.sf_mode] + AND CL,sharing_mask + CMP CL,sharing_compat + POP CX + JNE NO_HARD_ERR +HARD_ERR: + invoke LOCK_VIOLATION + retnc ; User wants Retrys +NO_HARD_ERR: + XOR CX,CX ;No bytes transferred + MOV AX,error_lock_violation + STC + return + +EndProc READ_LOCK_VIOLATION + +; Same as READ_LOCK_VIOLATION except for READOP. +; This entry used by NET_WRITE + procedure WRITE_LOCK_VIOLATION,NEAR + DOSAssume CS,,"Write_Lock_Violation" + ASSUME ES:NOTHING + Assert ISSFT,,"WriteLockViolation" + + MOV [READOP],1 + JMP ERR_ON_CHECK + +EndProc WRITE_LOCK_VIOLATION + + +Break + +; Inputs: +; Outputs of SETUP +; Function: +; Perform disk read +; Outputs: +; Carry clear +; CX = No. of bytes read +; ES:DI point to SFT +; SFT offset and cluster pointers updated +; Carry set +; CX = 0 +; ES:DI point to SFT +; AX has error code + + procedure DISKREAD,NEAR + DOSAssume CS,,"DiskRead" + ASSUME ES:NOTHING + + Assert ISSFT,,"DISKREAD" + PUSH ES:[DI.sf_firclus] ; set up 1st cluster # for FastSeek + POP [FSeek_firclus] ; 11/5/86 + + MOV AX,WORD PTR ES:[DI.sf_size] + MOV BX,WORD PTR ES:[DI.sf_size+2] + SUB AX,WORD PTR [BYTPOS] + SBB BX,WORD PTR [BYTPOS+2] + JB RDERR ;Read starts past EOF + JNZ ENUF ;More than 64k to EOF + OR AX,AX + JZ RDERR ;Read starts at EOF + CMP AX,CX + JAE ENUF ;I/O fits + MOV CX,AX ;Limit read to up til EOF +ENUF: + invoke CHECK_READ_LOCK ;IFS. check read lock ;AN000; + JNC Read_Ok ; There are no locks + return + +READ_OK: + LES BP,[THISDPB] + Assert ISDPB,,"DISKREAD/ReadOK" + MOV AL,ES:[BP.dpb_drive] ; set up drive # for FastSeek + MOV [FSeek_drive],AL ; 11/5/86 ;AN000; + + CALL BREAKDOWN + MOV CX,[CLUSNUM] + invoke FNDCLUS +;------------------------------------------------------------------------ +IF NOT IBMCOPYRIGHT + JC SET_ACC_ERR_DS ; fix to take care of I24 fail + ; migrated from 330a - HKN +ENDIF +;------------------------------------------------------------------------ + OR CX,CX + JZ SKIPERR +RDERR: + MOV [DISK_FULL],1 ;MS. EOF detection ;AN000; + MOV AH,0EH ;MS. read/data/fail ;AN000; + transfer WRTERR22 +RDLASTJ:JMP RDLAST +SETSFTJ2: JMP SETSFT + +CANOT_READ: + POP CX ; Clean stack + POP CX + POP BX + + entry SET_ACC_ERR_DS +ASSUME DS:NOTHING,ES:NOTHING + Context DS + + entry SET_ACC_ERR + DOSAssume CS,,"SET_ACC_ERR" + + XOR CX,CX + MOV AX,error_access_denied + STC + return + +SKIPERR: + MOV [LASTPOS],DX + MOV [CLUSNUM],BX + CMP [BYTCNT1],0 + JZ RDMID + invoke BUFRD + JC SET_ACC_ERR_DS +RDMID: + CMP [SECCNT],0 + JZ RDLASTJ + invoke NEXTSEC + JC SETSFTJ2 + MOV BYTE PTR [TRANS],1 ; A transfer is taking place +ONSEC: + MOV DL,[SECCLUSPOS] + MOV CX,[SECCNT] + MOV BX,[CLUSNUM] +RDLP: + invoke OPTIMIZE + JC SET_ACC_ERR_DS + PUSH DI + PUSH AX + PUSH BX + MOV [ALLOWED],allowed_RETRY + allowed_FAIL + allowed_IGNORE + MOV DS,WORD PTR [DMAADD+2] +ASSUME DS:NOTHING + PUSH DX + PUSH CX + invoke SET_RQ_SC_PARMS ;LB. do this for SC ;AN000; + +IF BUFFERFLAG + pushf + cmp [BUF_EMS_SAFE_FLAG], 1 + je safe_read + call save_map + call restore_user_map +safe_read: + popf +ENDIF + + invoke DREAD + +IF BUFFERFLAG + pushf + cmp [BUF_EMS_SAFE_FLAG], 1 + je safe_mapping + call save_user_map + call restore_map +safe_mapping: + popf +ENDIF + + POP BX + POP DX + JNC SKP_CANOT_READ + JMP CANOT_READ +SKP_CANOT_READ: + MOV [TEMP_VAR],BX ;LB. save sector count ;AN000; + MOV [TEMP_VAR2],DX ;LB. 1st sector ;AN000; +SCAN_NEXT: +;;;;;;; invoke GETCURHEAD ;LB. get buffer header ;AN000; + PUSH DX ;LB. save regs ;AN000; + PUSH AX ;LB. ;AN000; + PUSH BX ;LB. ;AN000; + MOV AX,DX ;LB. +; MOV DX,[HIGH_SECTOR] ;LB. HASH(sector#) and get entry # ;AN000; + XOR DX,DX ;LB. to avoid divide overflow ;AN000; + DIV [BUF_HASH_COUNT] ;LB. get remainder ;AN000; + ADD DX,DX ;LB. 8 bytes per entry ;AN000; + ADD DX,DX ;LB. ;AN000; + ADD DX,DX ;LB. times 8 ;AN000; + + LDS DI,[BUF_HASH_PTR] ;LB. get Hash Table addr ;AN000; + ADD DI,DX ;LB position to entry ;AN000; + CMP [DI.Dirty_Count],0 ;LB dirty hash entry ? ;AN000; + JNZ yesdirty ;LB yes and map it ;AN000; + POP BX ;LB. ;AN000; + POP AX ;LB. ;AN000; + POP DX ;LB. ;AN000; + +IF NOT BUFFERFLAG + JMP SHORT end_scan ;LB. ;AN000; +ELSE + JMP END_SCAN +ENDIF + +yesdirty: + MOV WORD PTR [CurHashEntry+2],DS ;LB. update current Hash entry ptr ;AN000; + MOV WORD PTR [CurHashEntry],DI ;LB. ;AN000; + MOV WORD PTR [LASTBUFFER],-1 ;LB. invalidate last buffer ;AN000; + MOV BX,[DI.EMS_PAGE_NUM] ;LB. logical page ;AN000; + +IF NOT BUFFERFLAG + LDS DI,[DI.BUFFER_BUCKET] ;LB. ds:di is 1st buffer addr ;AN000; + MOV [FIRST_BUFF_ADDR],DI ;LB. save first buff addr 1/19/88 ;AN000; + invoke SET_MAP_PAGE ;LB. activate handle if EMS there ;AN000; +ELSE +; int 3 + push ds + push di ; save hash ptr + + LDS DI,[DI.BUFFER_BUCKET] ;ds:di is 1st buffer addr + POP AX ; Recall transfer address + PUSH AX + PUSH DI ; Save search environment + PUSH DX ; F.C. no need for high sector, <64K + push cx + + MOV DX,[TEMP_VAR2] ;LB. get 1st sector # + SUB DX,WORD PTR [DI.buf_sector] ; How far into transfer? + NEG DX + MOV DI,AX + MOV AX,DX + MOV CX,ES:[BP.dpb_sector_size] + MUL CX + ADD DI,AX ; Put the buffer here + mov [CURADD], di + + pop cx + pop dx + pop di + + invoke SET_MAP_PAGE ;LB. activate handle if EMS there ;AN000; + pop di ; restore hash ptr. + pop ds + LDS DI,[DI.BUFFER_BUCKET] ;LB. ds:di is 1st buffer addr ;AN000; + MOV [FIRST_BUFF_ADDR],DI ;LB. save first buff addr 1/19/88 ;AN000; +ENDIF + ;AN000; + POP BX ;LB. ;AN000; + POP AX ;LB. ;AN000; + POP DX ;LB. ;AN000; + + + Assert ISDPB,,"DISKREAD/RdLp" + MOV AL,ES:[BP.dpb_drive] +NXTBUF: ; Must see if one of these sectors is buffered + invoke BUFF_RANGE_CHECK ;F.C. >32mb + JNC inrange ;LB. ;AN000; + mov DI,[DI.buf_next] ;LB. get next buffer 1/19/88 ;AN000; + JMP DONXTBUF ;LB. ;AN000; +inrange: + TEST [DI.buf_flags],buf_dirty + JZ CLBUFF ; Buffer is clean, so OK +; A sector has been read in when a dirty copy of it is in a buffer +; The buffered sector must now be read into the right place + POP AX ; Recall transfer address + PUSH AX + PUSH DI ; Save search environment + PUSH DX ; F.C. no need for high sector, <64K + + MOV DX,[TEMP_VAR2] ;LB. get 1st sector # + SUB DX,WORD PTR [DI.buf_sector] ; How far into transfer? + NEG DX + MOV SI,DI + MOV DI,AX + MOV AX,DX + MOV CX,ES:[BP.dpb_sector_size] + MUL CX + ADD DI,AX ; Put the buffer here + LEA SI,[SI].BUFINSIZ + SHR CX,1 + PUSH ES + MOV ES,WORD PTR [DMAADD+2] + REP MOVSW + JNC EVENMOV + MOVSB +EVENMOV: + POP ES + POP DX + POP DI + MOV AL,ES:[BP.dpb_drive] + invoke SCANPLACE ;LB. done with this chain ;AN000; + JMP SHORT end_scan ;LB. ;AN000; +CLBUFF: + invoke SCANPLACE +DONXTBUF: + CMP DI,[FIRST_BUFF_ADDR] ;LB. end of buffers ;AN000; + JNZ NXTBUF +end_scan: + ADD DX,1 ;LB. next sector # ;AN000; + ADC [HIGH_SECTOR],0 ;LB. ;AN000; + DEC [TEMP_VAR] ;LB. decrement count ;AN000; + JZ SCAN_DONE ;LB. scan next sector ;AN000; + JMP SCAN_NEXT ;LB. scan next sector ;AN000; +SCAN_DONE: + Context DS + POP CX + POP CX + POP BX + JCXZ RDLAST + invoke IsEOF ; test for eof on fat size + JAE SETSFT + MOV DL,0 + INC [LASTPOS] ; We'll be using next cluster + JMP RDLP + +RDLAST: + MOV AX,[BYTCNT2] + OR AX,AX + JZ SETSFT + MOV [BYTCNT1],AX + invoke NEXTSEC + JC SETSFT + MOV [BYTSECPOS],0 + invoke BUFRD + JNC SETSFT + JMP SET_ACC_ERR_DS + +; Inputs: +; [NEXTADD],[CLUSNUM],[LASTPOS] set to determine transfer size +; and set cluster fields +; Function: +; Update [THISSFT] based on the transfer +; Outputs: +; sf_position, sf_lstclus, and sf_cluspos updated +; ES:DI points to [THISSFT] +; CX No. of bytes transferred +; Carry clear + + entry SETSFT + DOSAssume CS,,"SetSFT" + ASSUME ES:NOTHING + + LES DI,[THISSFT] + +; Same as SETSFT except ES:DI already points to SFT + entry SETCLUS + DOSAssume CS,,"SetClus" + ASSUME ES:NOTHING + + Assert ISSFT,,"SetClus" + MOV CX,[NEXTADD] + SUB CX,WORD PTR [DMAADD] ; Number of bytes transfered + TEST ES:[DI.sf_flags],devid_device + JNZ ADDREC ; don't set clusters if device + MOV AX,[CLUSNUM] + MOV ES:[DI.sf_lstclus],AX + MOV AX,[LASTPOS] + MOV ES:[DI.sf_cluspos],AX + +; Inputs: +; ES:DI points to SFT +; CX is No. Bytes transferred +; Function: +; Update the SFT offset based on the transfer +; Outputs: +; sf_position updated to point to first byte after transfer +; ES:DI points to SFT +; CX No. of bytes transferred +; Carry clear + + entry AddRec + DOSAssume CS,,"AddRec" + ASSUME ES:NOTHING + + Assert ISSFT,,"AddRec" + JCXZ RET28 ; If no records read, don't change position + ADD WORD PTR ES:[DI.sf_position],CX ; Update current position + ADC WORD PTR ES:[DI.sf_position+2],0 +RET28: CLC + return +EndProc DISKREAD + +CODE ENDS + END + \ No newline at end of file diff --git a/v4.0/src/DOS/DISK3.ASM b/v4.0/src/DOS/DISK3.ASM new file mode 100644 index 0000000..306b34e --- /dev/null +++ b/v4.0/src/DOS/DISK3.ASM @@ -0,0 +1,662 @@ +; SCCSID = @(#)disk3.asm 1.3 85/07/26 +; SCCSID = @(#)disk3.asm 1.3 85/07/26 +TITLE DISK3 - Disk utility routines +NAME Disk3 +; Low level Read and write routines for local SFT I/O on files and devs +; +; DISKWRITE +; WRTERR +; +; Revision history: +; +; AN000 version 4.00 Jan. 1988 +; + +; +; get the appropriate segment definitions +; +.xlist +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +include version.inc +.cref +.list + +Installed = TRUE + + i_need THISSFT,DWORD + i_need DMAADD,DWORD + i_need SecClusPos,BYTE + i_need ClusNum,WORD + i_need Trans,BYTE + i_need BytPos,4 + i_need SecPos,DWORD ;F.C. >32mb ;AN000; + i_need BytSecPos,WORD + i_need BytCnt1,WORD + i_need BytCnt2,WORD + i_need SecCnt,WORD + i_need ThisDPB,DWORD + i_need LastPos,WORD + i_need ValSec,WORD ;F.C. >32mb ;AN000; + i_need GrowCnt,DWORD + i_need ALLOWED,BYTE + I_need JShare,DWORD + I_need FSeek_drive,BYTE ; DOS 4.00 ;AN000; + I_need FSeek_firclus,WORD ; DOS 4.00 ;AN000; + I_need FSeek_logclus,WORD ; DOS 4.00 ;AN000; + I_need HIGH_SECTOR,WORD ;F.C. >32mb ;AN000; + I_need HIGH_SECTOR_TEMP,WORD ;F.C. >32mb ;AN000; + I_need EXTERR,WORD ; DOS 4.00 ;AN000; + I_need EXTERR_LOCUS,BYTE ; DOS 4.00 ;AN000; + I_need EXTERR_ACTION,BYTE ; DOS 4.00 ;AN000; + I_need EXTERR_CLASS,BYTE ; DOS 4.00 ;AN000; + I_need EXITHOLD,DWORD ; DOS 4.00 ;AN000; + I_need DISK_FULL,BYTE ; DOS 4.00 ;AN000; + I_need SC_DRIVE,BYTE ; DOS 4.00 ;AN000; + I_need SC_CACHE_COUNT,WORD ; DOS 4.00 ;AN000; + I_need ThisDRV,BYTE ; DOS 4.00 ;AN000; + I_need User_In_AX,WORD ; DOS 4.00 ;AN000; + I_need DOS34_FLAG,WORD ; DOS 4.00 ;AN000; + I_need FIRST_BUFF_ADDR,WORD ; DOS 4.00 ;AN000; + +IF BUFFERFLAG + EXTRN SAVE_MAP:NEAR + EXTRN RESTORE_MAP:NEAR + EXTRN SAVE_USER_MAP:NEAR + EXTRN RESTORE_USER_MAP:NEAR + i_need BUF_EMS_SAFE_FLAG,BYTE + i_need BUF_EMS_MODE,BYTE +ENDIF + + + +Break + +; Inputs: +; Outputs of SETUP +; Function: +; Perform disk write +; Outputs: +; Carry clear +; CX = No. of bytes read +; ES:DI point to SFT +; SFT offset and cluster pointers updated +; Carry set +; CX = 0 +; ES:DI point to SFT +; AX has error code + + procedure DISKWRITE,NEAR + DOSAssume CS,,"DiskWrite" + ASSUME ES:NOTHING + + Assert ISSFT,,"DiskWrite" + PUSH ES:[DI.sf_firclus] ; set up 1st cluster # for FastSeek + POP [FSeek_firclus] + + invoke CHECK_WRITE_LOCK ;IFS. check write lock ;AN000; + JNC WRITE_OK ;IFS. lock check ok ;AN000; + return + +WRTEOFJ: + JMP WRTEOF + +WRITE_OK: + AND ES:[DI.sf_flags],NOT (sf_close_nodate OR devid_file_clean) + ; Mark file as dirty, clear no date on close + LES BP,[THISDPB] + Assert ISDPB,,"DiskWrite/WriteOk" + MOV AL,ES:[BP.dpb_drive] ; set up drive # for FastSeek + MOV [FSeek_drive],AL ; 11/5/86 DOS 4.00 + + invoke BREAKDOWN + MOV AX,WORD PTR [BYTPOS] + MOV DX,WORD PTR [BYTPOS+2] + JCXZ WRTEOFJ ;Make the file length = sf_position + ADD AX,CX + ADC DX,0 ; AX:DX=byte after last byte accessed +; +; Make sure divide won't overflow +; + MOV BX,ES:[BP.dpb_sector_size] +; CMP DX,BX ;F.C. >32mb 16 bit sector check ;AN000; +; JAE WrtErr ;F.C. >32mb ;AN000; + + CALL DIV32 ;F.C. perform 32 bit divide ;AN000; + MOV BX,AX ; Save last full sector + OR DX,DX + JNZ CALCLUS + SUB AX,1 ; AX must be zero base indexed ;AC000; + SBB [HIGH_SECTOR],0 ;F.C. >32mb ;AN000; +CALCLUS: + PUSH [HIGH_SECTOR] ;F.C. >32mb ;AN000; + CALL SHR32 ;F.C. >32mb ;AN000; + POP [HIGH_SECTOR] ;F.C. >32mb ;AN000; + +; SHR AX,CL ; Last cluster to be accessed + PUSH AX + PUSH DX ; Save the size of the "tail" + PUSH ES + LES DI,[THISSFT] + Assert ISSFT,,"DiskWrite/CalClus" + MOV AX,WORD PTR ES:[DI.sf_size] + MOV DX,WORD PTR ES:[DI.sf_size+2] + POP ES + + + + PUSH AX ;F.C. >32mb ;AN000; + MOV AX,DX ;F.C. >32mb ;AN000; + XOR DX,DX ;F.C. >32mb ;AN000; + DIV ES:[BP.dpb_sector_size] ;F.C. >32mb ;AN000; + MOV [HIGH_SECTOR_TEMP],AX ;F.C. >32mb ;AN000; + POP AX ;F.C. >32mb ;AN000; + + DIV ES:[BP.dpb_sector_size] + MOV CX,AX ; Save last full sector of current file + OR DX,DX + JZ NORNDUP + ADD AX,1 ; Round up if any remainder ;AC000; + ADC [HIGH_SECTOR_TEMP],0 ;F.C. >32mb ;AN000; +NORNDUP: + PUSH [HIGH_SECTOR_TEMP] ;F.C. >32mb ;AN000; + POP WORD PTR [VALSEC+2] ;F.C. >32mb ;AN000; + MOV WORD PTR [VALSEC],AX ;Number of sectors that have been written + XOR AX,AX + MOV WORD PTR [GROWCNT],AX + MOV WORD PTR [GROWCNT+2],AX + POP AX + + MOV DI,[HIGH_SECTOR] ;F.C. >32mb ;AN000; + CMP DI,[HIGH_SECTOR_TEMP] ;F.C. >32mb ;AN000; + JB NOGROW ;F.C. >32mb ;AN000; + JZ lowsec ;F.C. >32mb ;AN000; + SUB BX,CX ;F.C. >32mb ;AN000; + SBB DI,[HIGH_SECTOR_TEMP] ;F.C. >32mb di:bx no. of sectors ;AN000; + JMP yesgrow ;F.C. >32mb ;AN000; +lowsec: + MOV DI,0 ;F.C. >32mb + SUB BX,CX ; Number of full sectors + JB NOGROW + JZ TESTTAIL +yesgrow: + MOV CX,DX + XCHG AX,BX + MUL ES:[BP.dpb_sector_size] ; Bytes of full sector growth + MOV [HIGH_SECTOR],DX ;F.C. >32mb save dx ;AN000; + MOV [HIGH_SECTOR_TEMP],AX ;F.C. >32mb save ax ;AN000; + MOV AX,DI ;F.C. >32mb ;AN000; + MUL ES:[BP.dpb_sector_size] ;F.C. >32mb do higher word multiply ;AN000; + ADD AX,[HIGH_SECTOR] ;F.C. >32mb add lower value ;AN000; + MOV DX,AX ;F.C. >32mb DX:AX is the result of ;AN000; + MOV AX,[HIGH_SECTOR_TEMP] ;F.C. >32mb a 32 bit multiply ;AN000; + + SUB AX,CX ; Take off current "tail" + SBB DX,0 ; 32-bit extension + ADD AX,BX ; Add on new "tail" + ADC DX,0 ; ripple tim's head off + JMP SHORT SETGRW +HAVSTART: +;int 3 + MOV CX,AX + invoke SKPCLP + JCXZ DOWRTJ +;;; 11/5/86 FastSeek + MOV [FSeek_logclus],DX ; delete EOF (FFFFH) + INC [FSeek_logclus] + invoke FastSeek_Truncate ; +;;; 11/5/86 FastSeek + invoke ALLOCATE + JNC DOWRTJ + + entry WRTERR + DOSAssume CS,,"DiskWrite/WrtErr" + ASSUME ES:NOTHING + + MOV AH,0FH ;MS. write/data/fail/abort ;AN000; + entry WRTERR22 + MOV AL,[THISDRV] ;MS. ;AN000; + CALL File_Handle_Fail_Error ;MS. issue disk full I24 + MOV CX,0 ;No bytes transferred +; XOR CX,CX ; will be deleted + LES DI,[THISSFT] + Assert ISSFT,,"DiskWrite/WrtErr" +; CLC + return + +DOWRTJ: JMP DOWRT + +ACC_ERRWJ: + JMP SET_ACC_ERRW + +TESTTAIL: + SUB AX,DX + JBE NOGROW + XOR DX,DX +SETGRW: + MOV WORD PTR [GROWCNT],AX + MOV WORD PTR [GROWCNT+2],DX +NOGROW: + POP AX + MOV CX,[CLUSNUM] ; First cluster accessed + invoke FNDCLUS + JC ACC_ERRWJ + MOV [CLUSNUM],BX + MOV [LASTPOS],DX +;;; 11/5/86 FastSeek + MOV [FSeek_logclus],AX ; set up last position + SUB AX,DX ; Last cluster minus current cluster + JZ DOWRT ; If we have last clus, we must have first + JCXZ HAVSTART ; See if no more data + PUSH CX ; No. of clusters short of first + MOV CX,AX + +;;; 11/5/86 FastSeek + CMP [CLUSNUM],0 ;FS. null file ;AN000; + JZ NULL_FILE ;FS. yes ;AN000; + MOV [FSeek_logclus],DX ;FS. delete EOF (FFFFH) ;AN000; + INC [FSeek_logclus] ;FS. ;AN000; + invoke FastSeek_Truncate ;FS. ;AN000; +NULL_FILE: +;;; 11/5/86 FastSeek + invoke ALLOCATE + POP AX + JC WRTERR + MOV CX,AX + MOV DX,[LASTPOS] + INC DX + DEC CX + JZ NOSKIP +;;; 11/5/86 FastSeek + MOV [FSeek_logclus],DX ; + ADD [FSeek_logclus],CX ; set up last position + invoke SKPCLP + JC ACC_ERRWJ +NOSKIP: + MOV [CLUSNUM],BX + MOV [LASTPOS],DX +DOWRT: + CMP [BYTCNT1],0 + JZ WRTMID + MOV BX,[CLUSNUM] + invoke BUFWRT + JC ACC_ERRWJ +WRTMID: + MOV AX,[SECCNT] + OR AX,AX + JNZ havemid + JMP WRTLAST +havemid: + ADD WORD PTR [SECPOS],AX + ADC WORD PTR [SECPOS+2],0 ;F.C. >32mb ;AN000; + invoke NEXTSEC + JNC gotok + JMP ACC_ERRWJ +gotok: + MOV BYTE PTR [TRANS],1 ; A transfer is taking place + MOV DL,[SECCLUSPOS] + MOV BX,[CLUSNUM] + MOV CX,[SECCNT] +WRTLP: + invoke OPTIMIZE + JNC wokok + JMP ACC_ERRWJ +wokok: + PUSH DI + PUSH AX + PUSH DX + PUSH BX + Assert ISDPB,,"DiskWrite/WrtLp" + MOV AL,ES:[BP.dpb_drive] + MOV [SC_DRIVE],AL ;LB. save it for INVALIDATE_SC ;AN000; + PUSH CX ;LB. ;AN000; + PUSH [HIGH_SECTOR] ;LB. ;AN000; +SCANNEXT: ;LB. ;AN000; + invoke GETCURHEAD ;LB. ;AN000; +ASSUME DS:NOTHING +NEXTBUFF: ; Search for buffers + CMP [SC_CACHE_COUNT],0 ;LB. SC support ? ;AN000; + JZ nosc ;LB. no ;AN000; + PUSH AX ;LB. save reg ;AN000; + PUSH CX ;LB. save reg ;AN000; + PUSH DX ;LB. save reg ;AN000; + invoke INVALIDATE_SC ;LB. invalidate SC ;AN000; + POP DX ;LB. save reg ;AN000; + POP CX ;LB. save reg ;AN000; + POP AX ;LB. save reg ;AN000; +nosc: + CALL BUFF_RANGE_CHECK ;F.C. >32mb ;AN000; + JNC inrange2 ;F.C. >32mb ;AN000; + mov DI,[DI.buf_next] ;LB. get next buffer 1/19/88 ;AN000; + JMP DONEXTBUFF ;LB. ;AN000; +inrange2: + TEST [DI.buf_flags],buf_dirty ;LB. if dirty ;AN000; + JZ not_dirty ;LB. ;AN000; + invoke DEC_DIRTY_COUNT ;LB. then decrement dirty count ;AN000; +not_dirty: + MOV WORD PTR [DI.buf_ID],(buf_visit SHL 8) OR 0FFH ; Free the buffer, it is being over written + invoke SCANPLACE +DONEXTBUFF: + CMP DI,[FIRST_BUFF_ADDR] ;LB. end of chain ;AN000; + JNZ NEXTBUFF ;LB. no ;AN000; + ADD DX,1 ;LB. next sector number ;AN000; + ADC [HIGH_SECTOR],0 ;LB. ;AN000; + LOOP SCANNEXT ;LB. check again ;AN000; + POP [HIGH_SECTOR] ;LB. ;AN000; + POP CX ;LB. get count back ;AN000; + + POP BX + POP DX + MOV DS,WORD PTR [DMAADD+2] + MOV [ALLOWED],allowed_RETRY + allowed_FAIL + allowed_IGNORE + +IF BUFFERFLAG + pushf + cmp [BUF_EMS_MODE], -1 + je safe_write + call save_map + call restore_user_map +safe_write: + popf +ENDIF + + invoke DWRITE + +IF BUFFERFLAG + pushf + cmp [BUF_EMS_MODE], -1 + je safe_map + call save_user_map + call restore_map +safe_map: + popf +ENDIF + + POP CX + POP BX + Context DS + JC SET_ACC_ERRW + JCXZ WRTLAST + MOV DL,0 + INC [LASTPOS] ; We'll be using next cluster + JMP WRTLP + +WRTLAST: + MOV AX,[BYTCNT2] + OR AX,AX + JZ FINWRT + MOV [BYTCNT1],AX + invoke NEXTSEC + JC SET_ACC_ERRW + MOV [BYTSECPOS],0 + invoke BUFWRT + JC SET_ACC_ERRW +FINWRT: + LES DI,[THISSFT] + Assert ISSFT,,"DiskWrite/FinWrt" + MOV AX,WORD PTR [GROWCNT] + MOV CX,WORD PTR [GROWCNT+2] + OR AX,AX + JNZ UPDATE_size + JCXZ SAMSIZ +Update_size: + ADD WORD PTR ES:[DI.sf_size],AX + ADC WORD PTR ES:[DI.sf_size+2],CX +; +; Make sure that all other SFT's see this growth also. +; + MOV AX,1 +if installed + call JShare + 14 * 4 +else + Call ShSU +endif +SAMSIZ: + transfer SETCLUS ; ES:DI already points to SFT + +SET_ACC_ERRW: + transfer SET_ACC_ERR_DS + +WRTEOF: + MOV CX,AX + OR CX,DX + JZ KILLFIL + SUB AX,1 + SBB DX,0 + + PUSH BX + MOV BX,ES:[BP.dpb_sector_size] ;F.C. >32mb ;AN000; + CALL DIV32 ;F.C. >32mb ;AN000; + POP BX ;F.C. >32mb ;AN000; + CALL SHR32 ;F.C. >32mb ;AN000; + + +; SHR AX,CL + MOV CX,AX + invoke FNDCLUS +SET_ACC_ERRWJ2: + JC SET_ACC_ERRW +;;; 11/5/86 FastSeek + MOV [FSeek_logclus],DX ; truncate clusters starting from DX + invoke FastSeek_Truncate +;;; 11/5/86 FastSeek + JCXZ RELFILE + invoke ALLOCATE + JC WRTERRJ ;;;;;;;;; disk full +UPDATE: + LES DI,[THISSFT] + Assert ISSFT,,"DiskWrite/update" + MOV AX,WORD PTR [BYTPOS] + MOV WORD PTR ES:[DI.sf_size],AX + MOV AX,WORD PTR [BYTPOS+2] + MOV WORD PTR ES:[DI.sf_size+2],AX +; +; Make sure that all other SFT's see this growth also. +; + MOV AX,2 +if installed + Call JShare + 14 * 4 +else + Call ShSU +endif + XOR CX,CX + transfer ADDREC + +WRTERRJ: JMP WRTERR +;;;;;;;;;;;;;;;; 7/18/86 +;;;;;;;;;;;;;;;;; +RELFILE: + MOV DX,0FFFFH + invoke RELBLKS +Set_Acc_ERRWJJ: + JC SET_ACC_ERRWJ2 + JMP SHORT UPDATE + +KILLFIL: + XOR BX,BX + PUSH ES + LES DI,[THISSFT] + Assert ISSFT,,"DiskWrite/KillFil" + MOV ES:[DI.sf_cluspos],BX + MOV ES:[DI.sf_lstclus],BX + XCHG BX,ES:[DI.sf_firclus] + POP ES +;; 11/5/86 FastSeek + invoke Delete_FSeek ; delete fastseek entry + + OR BX,BX + JZ UPDATEJ +;; 10/23/86 FastOpen update + PUSH ES ; since first cluster # is 0 + PUSH BP ; we must delete the old cache entry + PUSH AX + PUSH CX + PUSH DX + LES BP,[THISDPB] ; get current DPB + MOV DL,ES:[BP.dpb_drive] ; get current drive + MOV CX,BX ; first cluster # + MOV AH,2 ; delete cache entry by drive:firclus + invoke FastOpen_Update ; call fastopen + POP DX + POP CX + POP AX + POP BP + POP ES +;; 10/23/86 FastOpen update + + invoke RELEASE + JC SET_ACC_ERRWJJ +UpDateJ: + JMP UPDATE +EndProc DISKWRITE + + + +Break + +; Inputs: +; DX:AX = 32 bit dividend BX= divisor +; Function: +; Perform 32 bit division +; Outputs: +; [HIGH_SECTOR]:AX = quotiend , DX= remainder + + procedure DIV32,NEAR + ASSUME DS:NOTHING,ES:NOTHING + + + PUSH AX ;F.C. >32mb ;AN000; + MOV AX,DX ;F.C. >32mb ;AN000; + XOR DX,DX ;F.C. >32mb ;AN000; + DIV BX ;F.C. >32mb ;AN000; + MOV [HIGH_SECTOR],AX ;F.C. >32mb ;AN000; + POP AX ;F.C. >32mb ;AN000; + + + DIV BX ; AX=last sector accessed + return + +EndProc DIV32 + +Break + +; Inputs: +; [HIGH_SECTOR]:AX = 32 bit sector number +; Function: +; Perform 32 bit shift right +; Outputs: +; AX= cluster number + + procedure SHR32,NEAR + ASSUME DS:NOTHING,ES:NOTHING + + + MOV CL,ES:[BP.dpb_cluster_shift] + XOR CH,CH +entry ROTASHFT ;F.C. >32mb ;AN000; + OR CX,CX ;F.C. >32mb ;AN000; + JZ norota ;F.C. >32mb ;AN000; +ROTASHFT2: + CLC ;F.C. >32mb ;AN000; + RCR [HIGH_SECTOR],1 ;F.C. >32mb ;AN000; + RCR AX,1 ;F.C. >32mb ;AN000; + LOOP ROTASHFT2 ;F.C. >32mb: ;AN000; +norota: + return + +EndProc SHR32 + + +; Issue File Handle Fail INT 24 Critical Error +; Input: Disk_Full=0 ok +; 1 disk full or EOF +; Function: issue critical error for disk full or EOF error +; +; OutPut: carry clear , no I24 +; carry set, fail from I24 + +procedure File_Handle_Fail_Error,NEAR ;AN000; + ASSUME ES:NOTHING,DS:NOTHING ;AN000; + ;AN000; + CMP [DISK_FULL],0 ;MS. disk full or EOF ;AN000; + JZ Fexit ;MS. no ;AN000; + TEST [DOS34_FLAG],Disable_EOF_I24 ;MS. check input status ? ;AN000; + JNZ Fexit ;MS. yes ;AN000; + ;AN000; + LES DI,[THISSFT] ;MS. get current SFT ;AN000; +; LES DI,ES:[DI.sf_DEVPTR];MS. get device header ;AN000; + TEST ES:[DI.sf_flags],Handle_Fail_I24 ;MS. gen I24 ? ;AN000; + JZ Fexit ;MS. no ;AN000; + PUSH DS ;MS. save DS ;AN000; + TEST AH,1 ;MS. READ ? ;AN000; + JZ readeof ;MS. yes ;AN000; + MOV [EXTERR],error_Handle_Disk_Full ;MS. set extended error ;AN000; + JMP SHORT errset ;MS. set extended error ;AN000; +readeof: + MOV [EXTERR],error_Handle_EOF ;MS. set extended error ;AN000; +errset: + MOV [EXTERR_CLASS],errCLASS_OutRes ;MS. set class ;AN000; + MOV [EXTERR_ACTION],errACT_Abort ;MS. set action ;AN000; + MOV [EXTERR_LOCUS],errLOC_Unk ;MS. set locus ;AN000; + MOV word ptr [EXITHOLD + 2],ES ;MS. save es:bp in exithold ;AN000; + MOV word ptr [EXITHOLD],BP ;MS. ;AN000; + TEST ES:[DI.sf_flags],devid_device ;MS. device ? ;AN000; + JNZ chardev2 ;MS. yes ;AN000; + LDS SI,ES:[DI.sf_DEVPTR] ;MS. get dpb ;AN000; + LDS SI,[SI.dpb_driver_addr] ;MS. get drive device haeder ;AN000; + JMP SHORT doi24 ;MS. gen I24 ? ;AN000; +chardev2: + LDS SI,ES:[DI.sf_DEVPTR] ;MS. get chr dev header ;AN000; +doi24: + MOV BP,DS ;MS. bp:si -> device header ;AN000; + MOV DI,error_I24_gen_failure ;MS. general error ;AN000; + invoke NET_I24_ENTRY ;MS. issue I24 ;AN000; + STC ;MS. must be fail ;AN000; + POP DS ;MS. restore DS ;AN000; + MOV AX,[EXTERR] ;MS. set error ;AN000; + JMP SHORT Fend ;MS. exit ;AN000; +Fexit: ;AN000; + CLC ;MS. clear carry ;AN000; +Fend: ;AN000; + return ;MS. ;AN000; + ;AN000; +EndProc File_Handle_Fail_Error ;AN000; + + +Break + +; Inputs: +; DS:DI -> buffer. AL= drive # +; [HIGH_SECTOR]:DX = sector # +; Function: +; check if sector is in the buffer +; Outputs: +; carry clear= in the range +; set = not in the range + + procedure BUFF_RANGE_CHECK,NEAR + ASSUME DS:NOTHING,ES:NOTHING + + CMP WORD PTR [DI.buf_sector],DX ;AN000; + JNZ DONEXTBUFF2 ; not this sector ;F.C. >32mb ;AN000; + MOV SI,[HIGH_SECTOR] ;F.C. >32mb ;AN000; + CMP WORD PTR [DI.buf_sector+2],SI ;F.C. >32mb ;AN000; + JNZ DONEXTBUFF2 ; Not for this drive + CMP AL,[DI.buf_ID] + JZ secfound ; Buffer has the sector ;AN000; +DONEXTBUFF2: + STC +secfound: + return + +EndProc BUFF_RANGE_CHECK + +CODE ENDS + END + \ No newline at end of file diff --git a/v4.0/src/DOS/DISP.ASM b/v4.0/src/DOS/DISP.ASM new file mode 100644 index 0000000..fba9764 --- /dev/null +++ b/v4.0/src/DOS/DISP.ASM @@ -0,0 +1,579 @@ +; SCCSID = @(#)disp.asm 1.1 85/04/10 +; SCCSID = @(#)disp.asm 1.1 85/04/10 +; +; Dispatcher code +; + +.xlist +.xcref +INCLUDE DOSSYM.INC +include dosseg.asm +.cref +.list + +AsmVars + +BREAK +CODE SEGMENT BYTE PUBLIC 'CODE' + + + I_need CurrentPDB,WORD + I_need CntCFlag,BYTE + I_need User_SS,WORD + I_need User_SP,WORD + I_need NSS,WORD + I_need NSP,WORD + I_need MaxCall,BYTE + I_need MaxCom,BYTE + I_need SaveDS,WORD + I_need SaveBX,WORD + I_need INDOS,BYTE + I_need User_ID,WORD + I_need Proc_ID,WORD + I_need AuxStack,BYTE + I_need IOSTACK,BYTE + I_need DSKSTACK,BYTE + I_need fsharing,BYTE + I_need NoSetDir,BYTE + I_need FailERR,BYTE + I_need Errormode,BYTE + I_need restore_tmp,WORD + I_need WPERR,BYTE + I_need Dispatch,WORD + I_need ConSwap,BYTE + I_need User_In_AX,WORD + I_need EXTERR_LOCUS,BYTE + I_need IdleInt,BYTE + I_need Printer_Flag,BYTE + I_need CPSWFLAG,BYTE ;AN000; + I_need CPSWSAVE,BYTE ;AN000; + I_need DISK_FULL,BYTE ;AN000; + I_need InterCon,BYTE ;AN000; + I_need BOOTDRIVE,BYTE ;AN000; + I_need EXTOPEN_ON,BYTE ;AN000; + I_need DOS34_FLAG,WORD ;AN000; + I_need ACT_PAGE,WORD ;AN000; + + IF NOT IBM + I_need OEM_HANDLER,DWORD + ENDIF + + IF BUFFERFLAG + I_am SETVECTFLAG,BYTE,<0> + i_need BUF_EMS_SEG_CNT,WORD ; DOS 4.00 EMS seg count ;AN000; + i_need BUF_EMS_MODE,BYTE ; DOS 4.00 EMS mode ;AN000; + i_am BUF_EMS_MAP_USER,12,<0,0,0,0,0,0,0,0,0,0,0,0> + ENDIF + +ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + +BREAK +ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + +BREAK <$Set_CTRL_C_Trapping -- En/Disable ^C check in dispatcher> + +; Inputs: +; AL = 0 read ^C status +; AL = 1 Set ^C status, DL = 0/1 for ^C off/on +; AL = 2 Set ^C status to contents of DL. Output is old state. +; AL = 3 Get CPSW state to DL DOS 3.4 +; AL = 4 Set CPSW state from DL DOS 3.4 +; AL = 5 get DOS boot drive +; Function: +; Enable disable ^C checking in dispatcher +; Outputs: +; If AL = 0 then DL = 0/1 for ^C off/on + + procedure $SET_CTRL_C_TRAPPING,NEAR +ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + OR AL,AL + JNZ Check1 + MOV DL,CntCFlag + IRET +Check1: + CMP AL,2 + JA CPSWchk ;AN000; + JZ SetAndRet + PUSH DX + AND DL,01h + MOV [CNTCFLAG],DL + POP DX + IRET +SetAndRet: + AND DL,01h + XCHG CntCFlag,DL + IRET +BadVal: + MOV AL,0FFH + IRET +;; DOS 4.00 File Tagging + +CPSWchk: ;AN000; +; PUSH AX ;AN000;;FT. +; MOV AL,[CPSWSAVE] ;AN000;;FT. DOS 3.4 +; MOV [CPSWFLAG],AL ;AN000;;FT. DOS 3.4 in case ABORT +; POP AX ;AN000;;FT. + CMP AL,3 ;AN000;;FT get CPSW state ? + JNZ CPSWset ;AN000;;FT. no +; MOV DL,CPSWFLAG ;AN000;;FT. return CPSW state + IRET ;AN000; +CPSWset: ;AN000; + CMP AL,4 ;AN000;;FT. set CPSW state ? + JA QueryDOSboot ;AN000;;FT. check query dos boot drive +; PUSH AX ;AN000;;FT. +; CallInstall NLSInstall,NLSFUNC,0 ;AN000;;FT. NLSFUNC installed ? +; CMP AL,0FFH ;AN000;;FT. +; POP AX ;AN000;;FT. +; JNZ BadVal ;AN000;;FT. not loaded, therefore ignore +;;;; AND DL,01H ;AN000;;FT. only 0 or 1 +;;;; MOV [CPSWFLAG],DL ;AN000;;FT. set the flag +;;;; MOV [CPSWSAVE],DL ;AN000;;FT. save one copy + IRET ;AN000;;FT. +QueryDOSboot: ;AN000; + CMP AL,5 ;AN000;MS. + JA BadVal ;AN000;MS. + MOV DL,[BOOTDRIVE] ;AN000;;MS. put boot drive in DL + IRET ;AN000;;MS. + + +;; DOS 4.00 File Tagging + +EndProc $SET_CTRL_C_TRAPPING + +BREAK <$Get_current_PDB -- Set/Get PDB value> +;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; +; C A V E A T P R O G R A M M E R ; +; ; +; The following two routines are dispatched to directly with ints disabled +; immediately after the int 21h entry. no DIS state is set. +; +; $Set_current_PDB takes BX and sets it to be the current process +; *** THIS FUNCTION CALL IS SUBJECT TO CHANGE!!! *** +; + procedure $SET_CURRENT_PDB,NEAR + ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + MOV [CurrentPDB],BX + IRET +EndProc $SET_CURRENT_PDB + +; +; $get_current_PDB returns in BX the current process +; *** THIS FUNCTION CALL IS SUBJECT TO CHANGE!!! *** +; +procedure $GET_CURRENT_PDB,NEAR + ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + MOV BX,[CurrentPDB] + IRET +EndProc $GET_CURRENT_PDB +; C A V E A T P R O G R A M M E R ; +; ; +;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; + +; +; Sets the Printer Flag to whatever is in AL. +; NOTE: THIS PROCEDURE IS SUBJECT TO CHANGE!!! +; +Procedure $Set_Printer_Flag +ASSUME DS:NOTHING, ES:NOTHING, SS:NOTHING + mov [Printer_Flag],al + IRET +EndProc $Set_Printer_Flag + + procedure SYSTEM_CALL,NEAR +; +; The Quit entry point is where all INT 20h's come from. These are old- style +; exit system calls. The CS of the caller indicates which Process is dying. +; The error code is presumed to be 0. We simulate an ABORT system call. +; + entry QUIT + MOV AH,0 + JMP SHORT SAVREGS +; +; The system call in AH is out of the range that we know how to handle. We +; arbitrarily set the contents of AL to 0 and IRET. Note that we CANNOT set +; the carry flag to indicate an error as this may break some programs +; compatability. +; +BADCALL: + MOV AL,0 + entry IRETT + IRET +; +; An alternative method of entering the system is to perform a CALL 5 in the +; program segment prefix with the contents of CL indicating what system call +; the user would like. A subset of the possible system calls is allowed here; +; only the CPM-compatible calls may get dispatched. +; + entry CALL_ENTRY ; System call entry point and dispatcher + POP AX ; IP from the long call at 5 + POP AX ; Segment from the long call at 5 + POP [User_SP] ; IP from the CALL 5 +; +; Re order the stack to simulate an interrupt 21. +; + PUSHF ; Start re-ordering the stack + CLI + PUSH AX ; Save segment + PUSH [User_SP] ; Stack now ordered as if INT had been used + CMP CL,MAXCALL ; This entry point doesn't get as many calls + JA BADCALL + MOV AH,CL + JMP SHORT SavRegs +; +; This is the normal INT 21 entry point. We first perform a quick test to see +; if we need to perform expensive DOS-entry functions. Certain system calls +; are done without interrupts being enabled. +; + +entry COMMAND ; Interrupt call entry point (INT 21H) + + IF NOT IBM + CMP AH,SET_OEM_HANDLER + JB NOTOEM + JMP $SET_OEM_HANDLER +NOTOEM: + ENDIF + + CMP AH,MAXCOM + JA BadCall + +; +; The following set of calls are issued by the server at *arbitrary* times +; and, therefore, must be executed on the user's entry stack and executed with +; interrupts off. +; +SAVREGS: + CMP AH,GET_CURRENT_PDB + JZ $GET_CURRENT_PDB + CMP AH,GetCurrentPSP + JZ $GET_CURRENT_PDB + CMP AH,SET_CURRENT_PDB + JZ $SET_CURRENT_PDB + CMP AH,Set_CTRL_C_Trapping + JNZ chkprt + JMP $Set_CTRL_C_Trapping +chkprt: + CMP AH,SET_PRINTER_FLAG + JZ $Set_Printer_Flag +; +; Preserve all user's registers on his own stack. +; + CALL save_world + MOV [SaveDS],DS + MOV [SaveBX],BX + MOV BX,CS + MOV DS,BX + ASSUME DS:DOSGROUP + INC [INDOS] ; Flag that we're in the DOS + XOR AX,AX + MOV [USER_ID],AX + MOV AX,CurrentPDB ; current process + MOV [PROC_ID],AX ; Assume local machine for the moment +; +; Provide one level of reentrancy for INT 24 recallability. +; + MOV AX,[user_SP] + MOV [NSP],AX + MOV AX,[user_SS] + MOV [NSS],AX + POP AX + PUSH AX + MOV [user_SP],SP + MOV [user_SS],SS +; +; save user stack in his area for later returns (possibly from EXEC) +; + MOV DS,[CurrentPDB] +ASSUME DS:NOTHING + MOV WORD PTR DS:[PDB_User_stack],SP + MOV WORD PTR DS:[PDB_User_stack+2],SS + + MOV fSharing,0 ; allow redirection + + MOV BX,CS ; no holes here. + MOV SS,BX +ASSUME SS:DOSGROUP + +entry REDISP + MOV SP,OFFSET DOSGROUP:AUXSTACK ; Enough stack for interrupts + STI ; stack is in our space now... + IF DBCS ;AN000; + MOV BH, BYTE PTR DS:[PDB_InterCon] ;AN000;; get interim mode 2/13/KK + MOV SS:[InterCon], BH ;AN000;; 2/13/KK + ENDIF ;AN000; + MOV BX,CS + MOV DS,BX + DOSAssume CS,,"MSCODE/ReDisp" +;; DOS 3.4 INIT +; MOV BL,[CPSWSAVE] ;AN000;;FT. DOS 3.4 +; MOV [CPSWFLAG],BL ;AN000;;FT. DOS 3.4 in case ABORT + MOV [DISK_FULL],0 ;AN000;;MS. no disk full + MOV [EXTOPEN_ON],0 ;AN000;;EO. clear extended open flag + MOV [DOS34_FLAG],0 ;AN000;;MS. clear common flag + MOV [ACT_PAGE],-1 ;BN000;BL;AN000;;LB. invalidate active page +;; DOS 4.00 INIT + XOR BH,BH + MOV [CONSWAP],BH ; random clean up of possibly mis-set flags + MOV [IDLEINT],1 ; presume that we can issue INT 28 + MOV BYTE PTR [NoSetDir],BH ; set directories on search + MOV BYTE PTR [FAILERR],BH ; FAIL not in progress + MOV BL,AH + SHL BX,1 ; 2 bytes per call in table + CLD +; +; Since the DOS maintains mucho state information across system calls, we +; must be very careful about which stack we use. +; +; First, all abort operations must be on the disk stack. THis is due to the +; fact that we may be hitting the disk (close operations, flushing) and may +; need to report an INT 24. +; + OR AH,AH + JZ DSKROUT ; ABORT +; +; Second, PRINT and PSPRINT and the server issue GetExtendedError calls at +; INT 28 and INT 24 time. This call MUST, therefore, use the AUXSTACK. +; + CMP AH,GetExtendedError + JZ DISPCALL +; +; Old 1-12 system calls may be either on the IOSTACK (normal operation) or +; on the AUXSTACK (at INT 24 time). +; + CMP AH,12 + JA DSKROUT + CMP [ERRORMODE],0 ; Are we in an INT 24? + JNZ DISPCALL ; Stay on AUXSTACK if INT 24. + MOV SP,OFFSET DOSGROUP:IOSTACK + JMP SHORT DISPCALL +; +; We are on a system call that is classified as "the rest". We place +; ourselves onto the DSKSTACK and away we go. We know at this point: +; +; o An INT 24 cannot be in progress. Therefore we reset errormode and +; wperr +; o That there can be no critical sections in effect. We signal the +; server to remove all the resources. +; +DSKROUT: + MOV [USER_IN_AX],AX ; Remember what user is doing + MOV [EXTERR_LOCUS],errLOC_Unk ; Default + MOV [ERRORMODE],0 ; Cannot make non 1-12 calls in + MOV [WPERR],-1 ; error mode, so good place to make +; +; Release all resource information +; + PUSH AX + MOV AH,82h + INT int_IBM + POP AX + +; +; Since we are going to be running on the DSKStack and since INT 28 people +; will use the DSKStack, we must turn OFF the generation of INT 28's. +; + MOV IdleInt,0 + MOV SP,OFFSET DOSGROUP:DSKSTACK + TEST [CNTCFLAG],-1 + JZ DISPCALL ; Extra ^C checking is disabled + PUSH AX + invoke DSKSTATCHK + POP AX +DISPCALL: + MOV BX,CS:Dispatch[BX] + XCHG BX,SaveBX + MOV DS,SaveDS + +IF BUFFERFLAG + mov cs:[SETVECTFLAG], 0 + cmp ah, 25h + jne saveuser + cmp ah, 35h + jne saveuser + mov cs:[SETVECTFLAG], 1 +saveuser: + invoke SAVE_USER_MAP ;AN000;LB. save EMS map +ENDIF + + ASSUME DS:NOTHING + CALL SaveBX + +IF BUFFERFLAG + invoke RESTORE_USER_MAP ;AN000;LB. retsore EMS map +ENDIF + + entry LEAVEDOS +ASSUME SS:NOTHING ; User routines may misbehave + CLI + DEC [INDOS] + MOV SS,[user_SS] + MOV SP,[user_SP] + MOV BP,SP + MOV BYTE PTR [BP.user_AX],AL + MOV AX,[NSP] + MOV [user_SP],AX + MOV AX,[NSS] + MOV [user_SS],AX + CALL restore_world + IRET +EndProc SYSTEM_CALL + +; +; restore_world restores all registers ('cept SS:SP, CS:IP, flags) from +; the stack prior to giving the user control +; + ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + procedure restore_world,NEAR + POP restore_tmp ; POP restore_tmp + POP AX ; PUSH ES + POP BX ; PUSH DS + POP CX ; PUSH BP + POP DX ; PUSH DI + POP SI ; PUSH SI + POP DI ; PUSH DX + POP BP ; PUSH CX + POP DS ; PUSH BX + POP ES ; PUSH AX + JMP restore_tmp ; PUSH restore_tmp +EndProc restore_world + +; +; save_world saves complete registers on the stack +; + ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + procedure save_world,NEAR + POP restore_tmp + PUSH ES + PUSH DS + PUSH BP + PUSH DI + PUSH SI + PUSH DX + PUSH CX + PUSH BX + PUSH AX + JMP restore_tmp ; PUSH restore_tmp +EndProc save_world + +IF BUFFERFLAG + +Break ;AN000; +; Inputs: ;AN000; +; none ;AN000; +; Function: ;AN000; +; save map ;AN000; +; Outputs: ;AN000; +; none ;AN000; +; No other registers altered ;AN000; + ;AN000; +Procedure SAVE_USER_MAP,NEAR ;AN000; + ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; + CMP cs:[BUF_EMS_MODE],-1 ;LB. EMS support ;AN000; + JZ No_user_save ;LB. no ;AN000; + CMP cs:[SETVECTFLAG], 1 + jz No_user_save +; MOV [ACT_PAGE],-1 ;LB. invalidate active page ;AN000; +; MOV WORD PTR [LASTBUFFER],-1 ;LB. and last buffer pointer ;AN000; + PUSH AX ;LB. save regs ;AN000; + PUSH DS ;LB. save regs ;AN000; + PUSH ES ;LB. ;AN000; + PUSH SI ;LB. ;AN000; + PUSH DI ;LB. ;AN000; + MOV SI,OFFSET DOSGROUP:BUF_EMS_SEG_CNT ;LB. ;AN000; + MOV DI,OFFSET DOSGROUP:BUF_EMS_MAP_USER ;LB. ;AN000; + + PUSH CS + POP ES + PUSH CS ;LB. ds:si -> ems seg cnt ;AN000; + POP DS ;LB. ;AN000; + + MOV AX,4F00H ;LB. save map ;AN000; + EnterCrit critDisk ;LB. enter critical section ;AN000; + INT 67H ;LB. ;AN000; + LeaveCrit critDisk ;LB. leave critical section ;AN000; + POP DI ;LB. ;AN000; + POP SI ;LB. restore regs ;AN000; + POP ES ;LB. ;AN000; + POP DS ;LB. ;AN000; + POP AX ;LB. restore ;AN000; +No_user_save: ;AN000; + return ;AN000; +EndProc SAVE_USER_MAP ;AN000; + ;AN000; + +Break ;AN000; +; Inputs: ;AN000; +; none ;AN000; +; Function: ;AN000; +; restore_map ;AN000; +; Outputs: ;AN000; +; none ;AN000; +; No other registers altered ;AN000; + ;AN000; +Procedure RESTORE_USER_MAP,NEAR ;AN000; + ASSUME DS:NOTHING,ES:NOTHING ;AN000; + + CMP cs:[BUF_EMS_MODE],-1 ;LB. EMS support ;AN000; + JZ No_user_restore ;LB. no ;AN000; + CMP cs:[SETVECTFLAG], 1 + jz No_user_restore + PUSH AX ;LB. save regs ;AN000; + PUSH DS ;LB. save regs ;AN000; + PUSH SI ;LB. ;AN000; + MOV SI,OFFSET DOSGROUP:BUF_EMS_MAP_USER ;LB. ;AN000; + + PUSH CS + POP DS + + MOV AX,4F01H ;LB. restore map ;AN000; + EnterCrit critDisk ;LB. enter critical section ;AN000; + INT 67H ;LB. ;AN000; + LeaveCrit critDisk ;LB. leave critical section ;AN000; + POP SI ;LB. restore regs ;AN000; + POP DS ;LB. ;AN000; + POP AX ;LB. ;AN000; +No_user_restore: ;AN000; + return ;AN000; +EndProc RESTORE_USER_MAP + +ENDIF + +; +; get_user_stack returns the user's stack (and hence registers) in DS:SI +; + procedure get_user_stack,NEAR + LDS SI,DWORD PTR [user_SP] + return +EndProc get_user_stack + + IF NOT IBM +BREAK LOW LEVEL <- +; check_signature, Coalesce +; * search.asm: DirSearchFirst, DirSearchNext, FindFirst, FindNext, +; PackName -> LOW LEVEL <- +; * proc.asm: Exec, Exit, Abort, Wait, KeepProcess +; * cpmio.asm: StdConInput, StdConOutput, StdAuxInput, StdAuxOutput, +; StdPrinterOutput, RawConIO, RawConInput, +; StdConInputNoEcho, StdConStringInput, +; StdConStringOutput, StdConInputStatus, +; StdConInputFlush +; OUT, BUFOUT, RAWOUT, RAWOUT2 -> LOW LEVEL <- +; * fcbio.asm: FCBOpen, FCBClose, FCBDelete, FCBSeqRead, FCBSeqWrite, +; FCBCreate, FCBRename, FCBRandomRead, FCBRandomWrite, +; GetFCBFileLength, GetFCBPosition, FCBRandomReadBlock, +; FCBRandomWriteBlock +; * Time.asm: GetDate, SetDate, GetTime, SetTime +; * Parse.asm: Parse_file_descriptor, PathParse +; * GetSet.asm: GetInterruptVector, SetInterruptVector, +; GetVerifyOnWrite, SetVerifyOnWrite, GetDMA, SetDMA, +; GetVersion, SetCTRLCTrapping, GetDriveFreespace, +; CharOper, International, SetDefaultDrive, +; GetDefaultDrive +; * Misc.asm: Sleazefunc, SleazefuncDL, GetDefaultDPB, GetDPB, +; CreateProcessDataBlock, GetINDOSFlag, GetInVars, +; SetDPB, DupPDB, DiskReset +; StrCmp, StrCpy, Ucase -> LOW LEVEL <- +; +; STUB MODULES +; Net.asm **** This will get broken down more??? +; * Share.asm Share_Check, Share_Violation +; * Lock.asm $LockOper +; DOS_LOCK,DOS_UNLOCK,Lock_Check, Lock_Violation + +; INTERNAL INTERFACE MODULES +; * Lock.asm DOS_LOCK, DOS_UNLOCK -->> STUBS <<-- +; * Dinfo.asm DISK_INFO +; * Finfo.asm GET_FILE_INFO, SET_FILE_ATTRIBUTE +; * Create.asm DOS_CREATE, DOS_CREATE_NEW, +; Set_Mknd_Err --> Low level routine <-- +; * Dup.asm DOS_DUP +; * Open.asm DOS_OPEN, +; SetBadPathError, --> Low level routines <-- +; Check_Access_AX, Share_Error, Set_SFT_Mode +; * Close.asm DOS_CLOSE, DOS_COMMIT, DOS_CLOSE_GOT_SFT, +; Free_SFT --> Low level routine <-- +; * Abort.asm DOS_ABORT +; * ISearch.asm DOS_SEARCH_FIRST, DOS_SEARCH_NEXT, +; RENAME_NEXT --> Low level routine <-- +; * Dircall.asm DOS_MKDIR, DOS_CHDIR, DOS_RMDIR +; * Rename.asm DOS_RENAME +; * Delete.asm DOS_DELETE, +; REN_DEL_Check --> Low level routine <-- +; * Disk.asm DOS_READ, DOS_WRITE + +; LOW LEVEL MODULES +; * Fat.asm UNPACK, PACK, MAPCLUSTER, FATREAD_SFT, +; FATREAD_CDS, FAT_operation +; * Ctrlc.asm --> STD/IBM versions <-- +; FATAL, FATAL1, reset_environment, DSKSTATCHK, +; SPOOLINT, STATCHK, CNTCHAND, DIVOV, RealDivOv, +; CHARHARD, HardErr +; * Buf.asm SETVISIT, ScanPlace, PLACEBUF, PLACEHEAD, PointComp, +; GETBUFFR, GETBUFFRB, FlushBuf, BufWrite, +; SKIPVISIT +; * Disk.asm SWAPBACK, SWAPCON, get_io_sft, DirRead, FATSecRd, +; DskRead, SETUP, BREAKDOWN, DISKREAD, DISKWRITE, +; FIRSTCLUSTER, DREAD, DWRITE, DSKWRITE, +; READ_LOCK_VIOLATION, WRITE_LOCK_VIOLATION, +; SETSFT, SETCLUS, AddRec +; * Mknode.asm BUILDDIR, SETDOTENT, MakeNode, NEWENTRY, FREEENT, +; NEWDIR, DOOPEN,RENAME_MAKE +; * FCB.asm MakeFcb, NameTrans, PATHCHRCMP, GetLet, TESTKANJ, +; NORMSCAN, CHK, DELIM +; * Rom.asm GET_random_record, GETRRPOS1, GetRRPos, SKPCLP, +; FNDCLUS, BUFSEC, BUFRD, BUFWRT, NEXTSEC, +; OPTIMIZE, FIGREC, GETREC, ALLOCATE, RESTFATBYT, +; RELEASE, RELBLKS, GETEOF +; * Dev.asm IOFUNC, DEVIOCALL, SETREAD, SETWRITE, GOTDPB, +; DEVIOCALL2, DEV_CLOSE_SFT, DEV_OPEN_SFT +; * Dir.asm SEARCH, SETDIRSRCH, GETPATH, ROOTPATH, StartSrch, +; MatchAttributes, DEVNAME, Build_device_ent, +; FindEntry, Srch, NEXTENT, GETENTRY, GETENT, +; NEXTENTRY, GetPathNoSet, FINDPATH +; + +; critical section information for the system calls + +; System Call Who takes care of the reentrancy +; Abort 0 (flushbuf) DOS_Close +; Std_Con_Input 1 DOS_Read +; Std_Con_Output 2 DOS_Write +; Std_Aux_Input 3 DOS_Read +; Std_Aux_Output 4 DOS_Write +; Std_Printer_Output 5 DOS_Write +; Raw_Con_IO 6 DOS_Read/DOS_Write +; Raw_Con_Input 7 DOS_Read +; Std_Con_Input_No_Echo 8 DOS_Read +; Std_Con_String_Output 9 DOS_Write +; Std_Con_String_Input A DOS_Read +; Std_Con_Input_Status B DOS_Read +; Std_Con_Input_Flush C DOS_Read +; Disk_Reset D (FlushBuf, ScanPlace, SkipVisit) +; Set_Default_Drive E *none* +; FCB_Open F DOS_Open +; FCB_Close 10 DOS_Close +; Dir_Search_First 11 DOS_Search_First +; Dir_Search_Next 12 DOS_Search_Next +; FCB_Delete 13 DOS_Delete +; FCB_Seq_Read 14 DOS_Read/DOS_Write +; FCB_Seq_Write 15 DOS_Read/DOS_Write +; FCB_Create 16 DOS_Create +; FCB_Rename 17 DOS_rename +; Get_Default_Drive 19 *none* +; Set_DMA 1A *none* +; Get_Default_DPB 1F *none* +; FCB_Random_Read 21 DOS_Read/DOS_Write +; FCB_Random_Write 22 DOS_Read/DOS_Write +; Get_FCB_File_Length 23 Get_file_info +; Get_FCB_Position 24 *none* +; Set_Interrupt_Vector 25 *none* +; Create_Process_Data_Block 26 *none* +; FCB_Random_Read_Block 27 DOS_Read/DOS_Write +; FCB_Random_Write_Block 28 DOS_Read/DOS_Write +; Parse_File_Descriptor 29 *none* +; Get_Date 2A DEVIOCALL +; Set_Date 2B DEVIOCALL +; Get_Time 2C DEVIOCALL +; Set_Time 2D DEVIOCALL +; Set_Verify_On_Write 2E *none* +; Get_DMA 2F *none* +; Get_Version 30 *none* +; Keep_Process 31 $abort... +; Get_DPB 32 *none* +; Set_CTRL_C_Trapping 33 *none* +; Get_InDOS_Flag 34 *none* +; Get_Interrupt_Vector 35 *none* +; Get_Drive_Freespace 36 Disk_Info +; Char_Oper 37 *none* +; International 38 *none* +; MKDir 39 DOS_MkDir +; RMDir 3A DOS_RmDir +; CHDir 3B DOS_ChDir +; Creat 3C DOS_Create +; Open 3D DOS_Open +; Close 3E DOS_Close +; Read 3F DOS_Read +; Write 40 DOS_Write +; Unlink 41 DOS_Delete +; LSeek 42 *none* +; CHMod 43 Get_file_info, Set_File_Attribute +; IOCtl 44 DEVIOCALL +; XDup 45 *none* +; XDup2 46 *none* +; Current_Dir 47 $Current_Dir +; Alloc 48 $Alloc +; Dealloc 49 $Dealloc +; Setblock 4A $SetBlock +; Exec 4B +; Exit 4C $abort... +; Wait 4D *none* +; Find_First 4E DOS_Search_First +; Find_Next 4F DOS_Search_Next +; Set_Current_PDB 50 *none* +; Get_Current_PDB 51 *none* +; Get_In_Vars 52 *none* +; SetDPB 53 *none* +; Get_Verify_On_Write 54 *none* +; Dup_PDB 55 +; Rename 56 DOS_Rename +; File_Times 57 *none* +; AllocOper 58 *none* +; GetExtendedError 59 *none* +; CreateTempFile 5A DOS_Create_New +; CreateNewFile 5B DOS_Create_New +; LockOper 5C +; ServerCall 5D +; UserOper 5E +; AssignOper 5F diff --git a/v4.0/src/DOS/DOSMES.ASM b/v4.0/src/DOS/DOSMES.ASM new file mode 100644 index 0000000..3770c5d --- /dev/null +++ b/v4.0/src/DOS/DOSMES.ASM @@ -0,0 +1,442 @@ +; SCCSID = @(#)dosmes.asm 1.7 85/10/23 +; SCCSID = @(#)dosmes.asm 1.7 85/10/23 +; +; Message file for Internationalized messages. There is +; only one message here available for translation. +; +; +; Revision history +; A000 version 4.00 Jan. 1988 +; + +IFNDEF KANJI +KANJI EQU FALSE +ENDIF + +IFNDEF Rainbow +Rainbow EQU FALSE +ENDIF + +include dossym.inc +include dosmac.inc +include doscntry.inc + +CONSTANTS SEGMENT WORD PUBLIC 'CONST' + + PUBLIC UserNum, OEMNum + Public DMES001S,DMES001E +DMES001S Label byte +USERNUM DW ? ; 24 bit user number + DB ? +IF IBM + IF IBMCOPYRIGHT + OEMNUM DB 0 ; 8 bit OEM number + ELSE + OEMNUM DB 0FFH ; 8 bit OEM number + ENDIF +ELSE +OEMNUM DB 0FFH +ENDIF + + +DMES001E label byte +CONSTANTS ENDS + +TABLE SEGMENT BYTE PUBLIC 'TABLE' +Public DMES002S +DMES002S label byte + + +; The following table is used for DOS 3.3 +;DOS country and code page information is defined here for DOS 3.3. +;The initial value for ccDosCountry is 1 (USA). +;The initial value for ccDosCodepage is 850. +; +; + PUBLIC COUNTRY_CDPG,UCASE_TAB,FILE_UCASE_TAB + PUBLIC FILE_CHAR_TAB +; +; country and code page infomation +; +COUNTRY_CDPG label byte + + db 0,0,0,0,0,0,0,0 ; reserved words + db '\COUNTRY.SYS',0 ; path name of country.sys + db 51 dup (?) + dw 437 ; system code page id + dw 6 ; number of entries + db SetUcase ; Ucase type + dw OFFSET DOSGROUP:UCASE_TAB ;pointer to upper case table + dw 0 ; segment of poiter + db SetUcaseFile ; Ucase file char type + dw OFFSET DOSGROUP:FILE_UCASE_TAB ;pointer to file upper case table + dw 0 ; segment of poiter + db SetFileList ; valid file chars type + dw OFFSET DOSGROUP:FILE_CHAR_TAB ;pointer to valid file char tab + dw 0 ; segment of poiter + db SetCollate ; collate type + dw OFFSET DOSGROUP:COLLATE_TAB ;pointer to collate table + dw 0 ; segment of poiter + db SetDBCS ;AN000; DBCS Ev 2/12/KK + dw OFFSET DOSGROUP:DBCS_TAB ;AN000;;pointer to DBCS Ev table 2/12/KK + dw 0 ;AN000; segment of poiter 2/12/KK + db SetCountryInfo ; country info type + dw NEW_COUNTRY_SIZE ; extended country info size + dw 1 ; USA country id + dw 437 ; USA system code page id + dw 0 ; date format + db '$',0,0,0,0 ; currency symbol + db ',',0 ; thousand separator + db '.',0 ; decimal separator + db '-',0 ; date separator + db ':',0 ; time separator + db 0 ; currency format flag + db 2 ; # of disgit in currency + db 0 ; time format + dw OFFSET DOSGROUP:MAP_CASE ;mono case routine entry point + dw 0 ; segment of entry point + db ',',0 ; data list separator + dw 0,0,0,0,0 ; reserved + + + +; +; +; +; +; +; upper case table +; +UCASE_TAB label byte + dw 128 + db 128,154,069,065,142,065,143,128 + db 069,069,069,073,073,073,142,143 + db 144,146,146,079,153,079,085,085 + db 089,153,154,155,156,157,158,159 + db 065,073,079,085,165,165,166,167 + db 168,169,170,171,172,173,174,175 + db 176,177,178,179,180,181,182,183 + db 184,185,186,187,188,189,190,191 + db 192,193,194,195,196,197,198,199 + db 200,201,202,203,204,205,206,207 + db 208,209,210,211,212,213,214,215 + db 216,217,218,219,220,221,222,223 + db 224,225,226,227,228,229,230,231 + db 232,233,234,235,236,237,238,239 + db 240,241,242,243,244,245,246,247 + db 248,249,250,251,252,253,254,255 + +; +; file upper case table +; +FILE_UCASE_TAB label byte + dw 128 + db 128,154,069,065,142,065,143,128 + db 069,069,069,073,073,073,142,143 + db 144,146,146,079,153,079,085,085 + db 089,153,154,155,156,157,158,159 + db 065,073,079,085,165,165,166,167 + db 168,169,170,171,172,173,174,175 + db 176,177,178,179,180,181,182,183 + db 184,185,186,187,188,189,190,191 + db 192,193,194,195,196,197,198,199 + db 200,201,202,203,204,205,206,207 + db 208,209,210,211,212,213,214,215 + db 216,217,218,219,220,221,222,223 + db 224,225,226,227,228,229,230,231 + db 232,233,234,235,236,237,238,239 + db 240,241,242,243,244,245,246,247 + db 248,249,250,251,252,253,254,255 + +; +; file char list +; +FILE_CHAR_TAB label byte + dw 22 ; length + db 1,0,255 ; include all + db 0,0,20h ; exclude 0 - 20h + db 2,14,'."/\[]:|<>+=;,' ; exclude 14 special + db 24 dup (?) ; reserved +; +; collate table +; +COLLATE_TAB label byte + dw 256 + db 0,1,2,3,4,5,6,7 + db 8,9,10,11,12,13,14,15 + db 16,17,18,19,20,21,22,23 + db 24,25,26,27,28,29,30,31 + db " ","!",'"',"#","$","%","&","'" + db "(",")","*","+",",","-",".","/" + db "0","1","2","3","4","5","6","7" + db "8","9",":",";","<","=",">","?" + db "@","A","B","C","D","E","F","G" + db "H","I","J","K","L","M","N","O" + db "P","Q","R","S","T","U","V","W" + db "X","Y","Z","[","\","]","^","_" + db "`","A","B","C","D","E","F","G" + db "H","I","J","K","L","M","N","O" + db "P","Q","R","S","T","U","V","W" + db "X","Y","Z","{","|","}","~",127 + db "C","U","E","A","A","A","A","C" + db "E","E","E","I","I","I","A","A" + db "E","A","A","O","O","O","U","U" + db "Y","O","U","$","$","$","$","$" + db "A","I","O","U","N","N",166,167 + db "?",169,170,171,172,"!",'"','"' + db 176,177,178,179,180,181,182,183 + db 184,185,186,187,188,189,190,191 + db 192,193,194,195,196,197,198,199 + db 200,201,202,203,204,205,206,207 + db 208,209,210,211,212,213,214,215 + db 216,217,218,219,220,221,222,223 + db 224,"S" + db 226,227,228,229,230,231 + db 232,233,234,235,236,237,238,239 + db 240,241,242,243,244,245,246,247 + db 248,249,250,251,252,253,254,255 +; +; dbcs is not supported in DOS 3.3 +; DBCS_TAB CC_DBCS <> +; +; DBCS for DOS 4.00 2/12/KK + PUBLIC DBCS_TAB +DBCS_TAB label byte ;AN000; 2/12/KK + dw 0 ;AN000; 2/12/KK max number + db 16 dup(0) ;AN000; 2/12/KK + +; dw 6 ; 2/12/KK +; db 081h,09fh ; 2/12/KK +; db 0e0h,0fch ; 2/12/KK +; db 0,0 ; 2/12/KK +; +; +include divmes.asm +include yesno.asm + +TABLE ENDS + +CODE SEGMENT BYTE PUBLIC 'CODE' +ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + +;CASE MAPPER ROUTINE FOR 80H-FFH character range, DOS 3.3 +; ENTRY: AL = Character to map +; EXIT: AL = The converted character +; Alters no registers except AL and flags. +; The routine should do nothing to chars below 80H. +; +; Example: + +Procedure MAP_CASE,FAR + CMP AL,80H + JAE Map1 ;Map no chars below 80H ever + RET +Map1: + SUB AL,80H ;Turn into index value + PUSH DS + PUSH BX + MOV BX,OFFSET DOSGROUP:UCASE_TAB + 2 +FINISH: + PUSH CS ;Move to DS + POP DS + XLAT ds:[bx] ;Get upper case character + POP BX + POP DS +L_RET: RET +EndProc MAP_CASE + +SUBTTL EDIT FUNCTION ASSIGNMENTS AND HEADERS +PAGE +; The following two tables implement the current buffered input editing +; routines. The tables are pairwise associated in reverse order for ease +; in indexing. That is; The first entry in ESCTAB corresponds to the last +; entry in ESCFUNC, and the last entry in ESCTAB to the first entry in ESCFUNC. + + +TABLE SEGMENT + PUBLIC CANCHAR +CANCHAR DB CANCEL ;Cancel line character + PUBLIC ESCCHAR +ESCCHAR DB ESCCH ;Lead-in character for escape sequences + IF NOT Rainbow +ESCTAB LABEL BYTE + IF NOT IBM + IF WANG + DB 0C0h ; ^Z inserter + DB 0C1H ; Copy one char + DB 0C1H ; Copy one char + DB 0C7H ; Skip one char + DB 08AH ; Copy to char + DB 088H ; Skip to char + DB 09AH ; Copy line + DB 0CBH ; Kill line (no change in template) + DB 08BH ; Reedit line (new template) + DB 0C3H ; Backspace + DB 0C6H ; Enter insert mode + DB 0D6H ; Exit insert mode + DB 0C6H ; Escape character + DB 0C6H ; End of table + ELSE + ; VT52 equivalences + DB "Z" ; ^Z inserter + DB "S" ; F1 Copy one char + DB "S" ; F1 Copy one char + DB "V" ; F4 Skip one char + DB "T" ; F2 Copy to char + DB "W" ; F5 Skip to char + DB "U" ; F3 Copy line + DB "E" ; SHIFT ERASE Kill line (no change in template) + DB "J" ; ERASE Reedit line (new template) + DB "D" ; LEFT Backspace + DB "P" ; BLUE Enter insert mode + DB "Q" ; RED Exit insert mode + DB "R" ; GRAY Escape character + DB "R" ; End of table + ENDIF + ENDIF + IF IBM + DB 64 ; Ctrl-Z - F6 + DB 77 ; Copy one char - --> + DB 59 ; Copy one char - F1 + DB 83 ; Skip one char - DEL + DB 60 ; Copy to char - F2 + DB 62 ; Skip to char - F4 + DB 61 ; Copy line - F3 + DB 61 ; Kill line (no change to template ) - Not used + DB 63 ; Reedit line (new template) - F5 + DB 75 ; Backspace - <-- + DB 82 ; Enter insert mode - INS (toggle) + DB 82 ; Exit insert mode - INS (toggle) + DB 65 ; Escape character - F7 + DB 65 ; End of table + ENDIF +ESCEND LABEL BYTE +ESCTABLEN EQU ESCEND-ESCTAB + +ESCFUNC LABEL WORD + short_addr GETCH ; Ignore the escape sequence + short_addr TWOESC + short_addr EXITINS + short_addr ENTERINS + short_addr BACKSP + short_addr REEDIT + short_addr KILNEW + short_addr COPYLIN + short_addr SKIPSTR + short_addr COPYSTR + short_addr SKIPONE + short_addr COPYONE + short_addr COPYONE + short_addr CTRLZ + ENDIF +TABLE ENDS + +; +; OEMFunction key is expected to process a single function +; key input from a device and dispatch to the proper +; routines leaving all registers UNTOUCHED. +; +; Inputs: CS, SS are DOSGROUP +; Outputs: None. This function is expected to JMP to one of +; the following labels: +; +; GetCh - ignore the sequence +; TwoEsc - insert an ESCChar in the buffer +; ExitIns - toggle insert mode +; EnterIns - toggle insert mode +; BackSp - move backwards one space +; ReEdit - reedit the line with a new template +; KilNew - discard the current line and start from scratch +; CopyLin - copy the rest of the template into the line +; SkipStr - read the next character and skip to it in the template +; CopyStr - read next char and copy from template to line until char +; SkipOne - advance position in template one character +; CopyOne - copy next character in template into line +; CtrlZ - place a ^Z into the template +; Registers that are allowed to be modified by this function are: +; AX, CX, BP + +Procedure OEMFunctionKey,NEAR + ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGROUP + IF DBCS ;AN000; +extrn intCNE0:near ;AN000; 2/17/KK + CALL intCNE0 ;AN000; 2/17/KK + ELSE ;AN000; + invoke $std_con_input_no_echo ; Get the second byte of the sequence + ENDIF ;AN000; + IF NOT Rainbow + MOV CL,ESCTABLEN ; length of table for scan + PUSH DI ; save DI (cannot change it!) + MOV DI,OFFSET DOSGROUP:ESCTAB ; offset of second byte table + REPNE SCASB ; Look it up in the table + POP DI ; restore DI + SHL CX,1 ; convert byte offset to word + MOV BP,CX ; move to indexable register + JMP [BP+OFFSET DOSGROUP:ESCFUNC] ; Go to the right routine + ENDIF + IF Rainbow + +TransferIf MACRO value,address + local a + CMP AL,value + JNZ a + transfer address +a: +ENDM + + CMP AL,'[' ; is it second lead char + JZ EatParm ; yes, go walk tree +GoGetCh: + transfer GetCh ; no, ignore sequence +EatParm: + invoke $std_con_input_no_echo ; get argument + CMP AL,'A' ; is it alphabetic arg? + JAE EatAlpha ; yes, go snarf one up + XOR BP,BP ; init digit counter + JMP InDigit ; jump into internal eat digit routine +EatNum: + invoke $std_con_input_no_echo ; get next digit +InDigit: + CMP AL,'9' ; still a digit? + JA CheckNumEnd ; no, go check for end char + SUB AL,'0' ; turn into potential digit + JL GoGetCh ; oops, not a digit, ignore + MOV CX,BP ; save BP for 10 multiply + CBW ; make AL into AX + SHL BP,1 ; 2*BP + SHL BP,1 ; 4*BP + ADD BP,CX ; 5*BP + SHL BP,1 ; 10*BP + ADD BP,AX ; 10*BP + digit + JMP EatNum ; continue with number +CheckNumEnd: + CMP AL,7Eh ; is it end char ~ + JNZ GoGetCh ; nope, ignore key sequence + MOV AX,BP + transferIf 1,SkipStr ; FIND key + transferIf 2,EnterIns ; INSERT HERE key + transferIf 3,SkipOne ; REMOVE + transferIf 4,CopyStr ; SELECT + transferIf 17,TwoEsc ; INTERRUPT + transferIf 18,ReEdit ; RESUME + transferIf 19,KilNew ; CANCEL + transferIf 21,CtrlZ ; EXIT + transferIf 29,CopyLin ; DO + JMP GoGetCh +EatAlpha: + CMP AL,'O' ; is it O? + JA GoGetCh ; no, after assume bogus + JZ EatPQRS ; eat the rest of the bogus key + transferIf 'C',CopyOne ; RIGHT + transferIf 'D',BackSp ; LEFT + JMP GoGetCh +EatPQRS: + invoke $std_con_input_no_echo ; eat char after O + JMP GoGetCh + ENDIF + +EndProc OEMFunctionKey + +CODE ENDS + + END diff --git a/v4.0/src/DOS/DOSPRINT.ASM b/v4.0/src/DOS/DOSPRINT.ASM new file mode 100644 index 0000000..92789cf --- /dev/null +++ b/v4.0/src/DOS/DOSPRINT.ASM @@ -0,0 +1,36 @@ +; SCCSID = @(#)dosprint.asm 1.1 85/04/10 +; SCCSID = @(#)dosprint.asm 1.1 85/04/10 +TITLE DOSPRINT - PRINTF at DOS level +NAME DOSPRINT +; +; +; Modification history: +; +; Created: MZ 16 June 1984 +; + +.xlist +; +; get the appropriate segment definitions +; +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGroup,CS:DOSGroup + +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +.cref +.list +.sall + + I_Need Proc_ID,WORD + I_Need User_ID,WORD + +BREAK + +include print.asm + +CODE ENDS +END diff --git a/v4.0/src/DOS/DUP.ASM b/v4.0/src/DOS/DUP.ASM new file mode 100644 index 0000000..0f8c768 --- /dev/null +++ b/v4.0/src/DOS/DUP.ASM @@ -0,0 +1,68 @@ +; SCCSID = @(#)dup.asm 1.1 85/04/10 +; SCCSID = @(#)dup.asm 1.1 85/04/10 +TITLE DOS_DUP - Internal SFT DUP (for network SFTs) +NAME DOS_DUP +; Low level DUP routine for use by EXEC when creating a new process. Exports +; the DUP to the server machine and increments the SFT ref count +; +; DOS_DUP +; +; Modification history: +; +; Created: ARR 30 March 1983 +; + +; +; get the appropriate segment definitions +; +.xlist +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +.cref +.list + + i_need THISSFT,DWORD + +BREAK + +; Inputs: +; [THISSFT] set to the SFT for the file being DUPed +; (a non net SFT is OK, in this case the ref +; count is simply incremented) +; Function: +; Signal to the devices that alogical open is occurring +; Returns: +; ES:DI point to SFT +; Carry clear +; SFT ref_count is incremented +; Registers modified: None. +; NOTE: +; This routine is called from $CREATE_PROCESS_DATA_BLOCK at DOSINIT +; time with SS NOT DOSGROUP. There will be no Network handles at +; that time. + + procedure DOS_DUP,NEAR + ASSUME ES:NOTHING,SS:NOTHING + + LES DI,ThisSFT + Entry Dos_Dup_Direct + Assert ISSFT,,"DOSDup" + invoke IsSFTNet + JNZ DO_INC + invoke DEV_OPEN_SFT +DO_INC: + Assert ISSFT,,"DOSDup/DoInc" + INC ES:[DI.sf_ref_count] ; Clears carry (if this ever wraps + ; we're in big trouble anyway) + return + +EndProc DOS_DUP + +CODE ENDS + END diff --git a/v4.0/src/DOS/EXEC.ASM b/v4.0/src/DOS/EXEC.ASM new file mode 100644 index 0000000..aa120c2 --- /dev/null +++ b/v4.0/src/DOS/EXEC.ASM @@ -0,0 +1,931 @@ +; SCCSID = @(#)exec.asm 1.3 85/08/13 +; SCCSID = @(#)exec.asm 1.3 85/08/13 +; AN000 version 4.0 jan. 1988 +; A007 PTM 3957 - fake vesrion for IBMCACHE.COM +; A008 PTM 4070 - fake version for MS WINDOWS + +SUBTTL $exec - load/go a program +PAGE +; +; Assembler usage: +; LDS DX, name +; LES BX, blk +; MOV AH, Exec +; MOV AL, func +; INT int_command +; +; AL Function +; -- -------- +; 0 Load and execute the program. +; 1 Load, create the program header but do not +; begin execution. +; 3 Load overlay. No header created. +; +; AL = 0 -> load/execute program +; +; +---------------------------+ +; | WORD segment address of | +; | environment. | +; +---------------------------+ +; | DWORD pointer to ASCIZ | +; | command line at 80h | +; +---------------------------+ +; | DWORD pointer to default | +; | FCB to be passed at 5Ch | +; +---------------------------+ +; | DWORD pointer to default | +; | FCB to be passed at 6Ch | +; +---------------------------+ +; +; AL = 1 -> load program +; +; +---------------------------+ +; | WORD segment address of | +; | environment. | +; +---------------------------+ +; | DWORD pointer to ASCIZ | +; | command line at 80h | +; +---------------------------+ +; | DWORD pointer to default | +; | FCB to be passed at 5Ch | +; +---------------------------+ +; | DWORD pointer to default | +; | FCB to be passed at 6Ch | +; +---------------------------+ +; | DWORD returned value of | +; | CS:IP | +; +---------------------------+ +; | DWORD returned value of | +; | SS:IP | +; +---------------------------+ +; +; AL = 3 -> load overlay +; +; +---------------------------+ +; | WORD segment address where| +; | file will be loaded. | +; +---------------------------+ +; | WORD relocation factor to | +; | be applied to the image. | +; +---------------------------+ +; +; Returns: +; AX = error_invalid_function +; = error_bad_format +; = error_bad_environment +; = error_not_enough_memory +; = error_file_not_found +; +; Revision history: +; +; A000 version 4.00 Jan. 1988 +; +include EA.INC +include version.inc + + I_Need Temp_Var2,WORD ;AN000;file type from $open + I_Need Special_Entries,WORD ;AN007;address of special entries + I_Need Special_Version,WORD ;AN007;special version number + I_Need Fake_Count,BYTE ;AN008;fake version count + +IF BUFFERFLAG + extrn restore_user_map:near +ENDIF + +TABLE SEGMENT + +exec_init_SP DW ? +exec_init_SS DW ? +exec_init_IP DW ? +exec_init_CS DW ? + +exec_internal_buffer EQU OpenBuf + +exec_signature DW ? ; must contain 4D5A (yay zibo!) +exec_len_mod_512 DW ? ; low 9 bits of length +exec_pages DW ? ; number of 512b pages in file +exec_rle_count DW ? ; count of reloc entries +exec_par_dir DW ? ; number of paragraphs before image +exec_min_BSS DW ? ; minimum number of para of BSS +exec_max_BSS DW ? ; max number of para of BSS +exec_SS DW ? ; stack of image +exec_SP DW ? ; SP of image +exec_chksum DW ? ; checksum of file (ignored) +exec_IP DW ? ; IP of entry +exec_CS DW ? ; CS of entry +exec_rle_table DW ? ; byte offset of reloc table +Exec_header_len EQU $-Exec_Signature + +exec_internal_buffer_size EQU (128+128+53+curdirLEN) +%out Please make sure that the following are contiguous and of the +%out following sizes: +%out +%out OpenBuf 128 +%out RenBuf 128 +%out SearchBuf 53 +%out DummyCDS CurDirLen + +TABLE ENDS + +.sall + +procedure $Exec,NEAR + ASSUME DS:NOTHING, ES:NOTHING +PUBLIC EXEC001S,EXEC001E +EXEC001S: + LocalVar exec_blk,DWORD + LocalVar exec_func,BYTE + LocalVar exec_load_high,BYTE + LocalVar exec_fh,WORD + LocalVar exec_rel_fac,WORD + LocalVar exec_res_len_para,WORD + LocalVar exec_environ,WORD + LocalVar exec_size,WORD + LocalVar exec_load_block,WORD + LocalVar exec_dma,WORD + LocalVar execNameLen,WORD + LocalVar execName,DWORD +EXEC001E: + Enter +; +; validate function +; + + CMP AL,3 ; only 0, 1 or 3 are allowed + JNA exec_check_2 + +exec_bad_fun: + MOV EXTERR_LOCUS,errLOC_Unk ; Extended Error Locus + mov al,error_invalid_function + +exec_ret_err: + Leave + transfer SYS_RET_ERR + +exec_check_2: + CMP AL,2 + JZ exec_bad_fun + + MOV exec_blkL,BX ; stash args + MOV exec_blkH,ES + MOV exec_func,AL + MOV exec_load_high,0 +; +; set up length of exec name +; + MOV execNameL,DX + MOV execNameH,DS + MOV SI,DX ; move pointer to convenient place + invoke DStrLen + MOV ExecNameLen,CX ; save length + + XOR AL,AL ; open for reading + PUSH BP + invoke $OPEN ; is the file there? + POP BP + JC exec_ret_err +;File Type Checking +; CMP BYTE PTR [Temp_Var2],EAEXISTING ;AN000;;FT. old file ? +; JZ oldexf ;AN000;;FT. yes +; TEST BYTE PTR EXEC_FUNC,EXEC_FUNC_OVERLAY ;AN000;;FT. exec overlay? +; JNZ exovrly ;AN000;;FT. yes +; CMP BYTE PTR [Temp_Var2],EAEXECUTABLE ;AN000;;FT. only file type +; JZ oldexf ;AN000;;FT. 3 & 4 will pass +; CMP BYTE PTR [Temp_Var2],EAINSTALLABLE ;AN000;;FT. +; JZ oldexf ;AN000;;FT. +;exerr: ;AN000;;FT. +; MOV AL,error_access_denied ;AN000;;FT. error +; JMP exec_ret_err ;AN000;;FT. +;exovrly: ;AN000;;FT. +; CMP BYTE PTR [Temp_Var2],EAOVERLAY ;AN000;;FT. only 5,6,7 pass +; JZ oldexf ;AN000;;FT. +; CMP BYTE PTR [Temp_Var2],EADEV_DRIVER ;AN000;;FT. +; JZ oldexf ;AN000;;FT. +; CMP BYTE PTR [Temp_Var2],EAIFS_DRIVER ;AN000;;FT. +; JNZ exerr ;AN000;;FT. +; +;oldexf: ;AN000; +;File Type Checking + + MOV exec_fh,AX + MOV BX,AX + XOR AL,AL + invoke $IOCTL + JC Exec_bombJ + TEST DL,devid_ISDEV + JZ exec_check_environ + MOV AL,error_file_not_found +Exec_bombJ: + JMP Exec_Bomb + +BadEnv: + MOV AL,error_bad_environment + JMP exec_bomb + +exec_check_environ: + MOV exec_load_block,0 + MOV exec_environ,0 + + TEST BYTE PTR exec_func,exec_func_overlay ; overlays... no environment + JNZ exec_read_header + LDS SI,exec_blk ; get block + MOV AX,[SI].Exec1_environ ; address of environ + OR AX,AX + JNZ exec_scan_env + MOV DS,CurrentPDB + MOV AX,DS:[PDB_environ] + MOV exec_environ,AX + OR AX,AX + JZ exec_read_header + +exec_scan_env: + MOV ES,AX + XOR DI,DI + MOV CX,07FFFh ; at most 32k of environment + XOR AL,AL + +exec_get_environ_len: + REPNZ SCASB ; find that nul byte + JNZ BadEnv + DEC CX ; Dec CX for the next nul byte test + JB BadEnv ; gone beyond the end of the environment + SCASB ; is there another nul byte? + JNZ exec_get_environ_len ; no, scan some more + PUSH DI + LEA BX,[DI+0Fh+2] + ADD BX,ExecNameLen ; BX <- length of environment + ; remember argv[0] length + ; round up and remember argc + MOV CL,4 + SHR BX,CL ; number of paragraphs needed + PUSH ES + invoke $ALLOC ; can we get the space? + POP DS + POP CX + JNC exec_save_environ + JMP exec_no_mem ; nope... cry and sob + +exec_save_environ: + MOV ES,AX + MOV exec_environ,AX ; save him for a rainy day + XOR SI,SI + MOV DI,SI + REP MOVSB ; copy the environment + MOV AX,1 + STOSW + LDS SI,execName + MOV CX,execNameLen + REP MOVSB + +exec_read_header: +; +; We read in the program header into the above data area and determine +; where in this memory the image will be located. +; + Context DS + MOV CX,exec_header_len ; header size + MOV DX,OFFSET DOSGROUP:exec_signature + PUSH ES + PUSH DS + CALL ExecRead + POP DS + POP ES + JC exec_bad_file + OR AX,AX + JZ exec_bad_file + CMP AX,exec_header_len ; did we read the right number? + JNZ exec_com_filej ; yep... continue + TEST exec_max_BSS,-1 ; indicate load high? + JNZ exec_check_sig + MOV exec_load_high,-1 +exec_check_sig: + MOV AX,exec_signature + CMP AX,exe_valid_signature ; zibo arises! + JZ exec_save_start ; assume com file if no signature + CMP AX,exe_valid_old_signature ; zibo arises! + JZ exec_save_start ; assume com file if no signature + +exec_com_filej: + JMP exec_com_file + +; +; We have the program header... determine memory requirements +; +exec_save_start: + MOV AX,exec_pages ; get 512-byte pages + MOV CL,5 ; convert to paragraphs + SHL AX,CL + SUB AX,exec_par_dir ; AX = size in paragraphs + MOV exec_res_len_para,AX + +; +; Do we need to allocate memory? Yes if function is not load-overlay +; + TEST BYTE PTR exec_func,exec_func_overlay + JZ exec_allocate ; allocation of space +; +; get load address from block +; + LES DI,exec_blk + MOV AX,ES:[DI].exec3_load_addr + MOV exec_dma,AX + MOV AX,ES:[DI].exec3_reloc_fac + MOV exec_rel_fac,AX +IF DEBUG + JMP exec_find_res +ELSE + JMP SHORT exec_find_res +ENDIF + +exec_no_mem: + MOV AL,error_not_enough_memory + JMP SHORT exec_bomb + +exec_bad_file: + MOV AL,error_bad_format + +exec_bomb: + ASSUME DS:NOTHING,ES:NOTHING + MOV BX,exec_fh + CALL exec_dealloc + LeaveCrit CritMem + SaveReg + invoke $CLOSE + RestoreReg + JMP Exec_Ret_Err + +exec_allocate: + DOSAssume CS,,"EXEC/exec_allocate" + PUSH AX + MOV BX,0FFFFh ; see how much room in arena + PUSH DS + invoke $ALLOC ; should have carry set and BX has max + POP DS + POP AX + ADD AX,10h ; room for header + CMP BX,11h ; enough room for a header + JB exec_no_mem + CMP AX,BX ; is there enough for bare image? + JA exec_no_mem + TEST exec_load_high,-1 ; if load high, use max + JNZ exec_BX_max ; use max + ADD AX,exec_min_BSS ; go for min allocation + JC exec_no_mem ; oops! carry + CMP AX,BX ; enough space? + JA exec_no_mem ; nope... + SUB AX,exec_min_BSS + ADD AX,exec_max_BSS ; go for the MAX + JC exec_BX_max + CMP AX,BX + JBE exec_got_block + +exec_BX_max: + MOV AX,BX + +exec_got_block: + PUSH DS + MOV BX,AX + MOV exec_size,BX + invoke $ALLOC ; get the space + POP DS + JC exec_no_mem + MOV exec_load_block,AX + ADD AX,10h + TEST exec_load_high,-1 + JZ exec_use_ax ; use ax for load info + ADD AX,exec_size ; go to end + SUB AX,exec_res_len_para ; drop off header + SUB AX,10h ; drop off pdb +exec_use_ax: + MOV exec_rel_fac,AX ; new segment + MOV exec_dma,AX ; beginning of dma + +; +; Determine the location in the file of the beginning of the resident +; +exec_find_res: + MOV DX,exec_par_dir + PUSH DX + MOV CL,4 + SHL DX,CL ; low word of location + POP AX + MOV CL,12 + SHR AX,CL ; high word of location + MOV CX,AX ; CX <- high + +; +; Read in the resident image (first, seek to it) +; + MOV BX,exec_fh + PUSH DS + XOR AL,AL + invoke $LSEEK ; seek to resident + POP DS + jnc exec_big_read + jmp exec_bomb + +exec_big_read: ; Read resident into memory + MOV BX,exec_res_len_para + CMP BX,1000h ; too many bytes to read? + JB exec_read_ok + MOV BX,0FE0h ; max in one chunk FE00 bytes + +exec_read_ok: + SUB exec_res_len_para,BX ; we read (soon) this many + PUSH BX + MOV CL,4 + SHL BX,CL ; get count in bytes from paras + MOV CX,BX ; count in correct register + PUSH DS + MOV DS,exec_dma ; Set up read buffer + ASSUME DS:NOTHING + XOR DX,DX + PUSH CX ; save our count + CALL ExecRead + POP CX ; get old count to verify + POP DS + JC exec_bad_fileJ + DOSAssume CS,,"EXEC/exec_read_ok" + CMP CX,AX ; did we read enough? + POP BX ; get paragraph count back + JZ execCheckEnd ; and do reloc if no more to read +; +; The read did not match the request. If we are off by 512 bytes or more +; then the header lied and we have an error. +; + SUB CX,AX + CMP CX,512 + JAE Exec_Bad_fileJ +; +; We've read in CX bytes... bump DTA location +; +ExecCheckEnd: + ADD exec_dma,BX ; bump dma address + TEST exec_res_len_para,-1 + JNZ exec_big_read +; +; The image has now been read in. We must perform relocation to +; the current location. +; +exec_do_reloc: + MOV CX,exec_rel_fac + MOV AX,exec_SS ; get initial SS + ADD AX,CX ; and relocate him + MOV exec_init_SS,AX + + MOV AX,exec_SP ; initial SP + MOV exec_init_SP,AX + + LES AX,DWORD PTR exec_IP + MOV exec_init_IP,AX + MOV AX,ES + ADD AX,CX ; relocated... + MOV exec_init_CS,AX + + XOR CX,CX + MOV DX,exec_rle_table + MOV BX,exec_fh + PUSH DS + XOR AX,AX + invoke $LSEEK + POP DS + + JNC exec_get_entries +exec_bad_filej: + JMP exec_bad_file + +exec_get_entries: + MOV DX,exec_rle_count ; Number of entries left + +exec_read_reloc: + ASSUME DS:NOTHING + PUSH DX + MOV DX,OFFSET DOSGROUP:exec_internal_buffer + MOV CX,((exec_internal_buffer_size)/4)*4 + PUSH DS + CALL ExecRead + POP ES + POP DX + JC exec_bad_filej + MOV CX,(exec_internal_buffer_size)/4 + MOV DI,OFFSET DOSGROUP:exec_internal_buffer ; Pointer to byte location in header +; +; Relocate a single address +; + MOV SI,exec_rel_fac + +exec_reloc_one: + OR DX,DX ; Any more entries? + JE exec_set_PDBJ + +exec_get_addr: + LDS BX,DWORD PTR ES:[DI] ; Get ra/sa of entry + MOV AX,DS ; Relocate address of item + ADD AX,SI + MOV DS,AX + ADD [BX],SI + ADD DI,4 + DEC DX + LOOP exec_reloc_one ; End of internal buffer? + +; +; We've exhausted a single buffer's worth. Read in the next piece +; of the relocation table. +; + + PUSH ES + POP DS + JMP exec_read_reloc + +exec_set_PDBJ: + JMP exec_set_PDB + +exec_no_memj: + JMP exec_no_mem + +; +; we have a .COM file. First, determine if we are merely loading an overlay. +; +exec_com_file: + TEST BYTE PTR exec_func,exec_func_overlay + JZ exec_alloc_com_file + LDS SI,exec_blk ; get arg block + LODSW ; get load address + MOV exec_dma,AX + MOV AX,0FFFFh + JMP SHORT exec_read_block ; read it all! + +; We must allocate the max possible size block (ick!) and set up +; CS=DS=ES=SS=PDB pointer, IP=100, SP=max size of block. +; +exec_alloc_com_file: + MOV BX,0FFFFh + invoke $ALLOC ; largest piece available as error + OR BX,BX + JZ exec_no_memj + MOV exec_size,BX ; save size of allocation block + PUSH BX + invoke $ALLOC ; largest piece available as error + POP BX ; get size of block... + MOV exec_load_block,AX + ADD AX,10h ; increment for header + MOV exec_dma,AX + XOR AX,AX ; presume 64K read... + CMP BX,1000h ; 64k or more in block? + JAE exec_read_com ; yes, read only 64k + MOV AX,BX ; convert size to bytes + MOV CL,4 + SHL AX,CL +exec_read_com: + SUB AX,100h ; remember size of psp +exec_read_block: + PUSH AX ; save number to read + MOV BX,exec_fh ; of com file + XOR CX,CX ; but seek to 0:0 + MOV DX,CX + XOR AX,AX ; seek relative to beginning + invoke $LSEEK ; back to beginning of file + POP CX ; number to read + MOV DS,exec_dma + XOR DX,DX + PUSH CX + CALL ExecRead + POP SI ; get number of bytes to read + jnc OkRead + jmp exec_bad_file +OkRead: + CMP AX,SI ; did we read them all? + JZ exec_no_memj ; exactly the wrong number... no memory + TEST BYTE PTR exec_func,exec_func_overlay + JNZ exec_set_PDB ; no starto, chumo! + MOV AX,exec_DMA + SUB AX,10h + MOV exec_init_CS,AX + MOV exec_init_IP,100h ; initial IP is 100 +; +; SI is at most FF00h. Add FE to account for PSP - word of 0 on stack. +; + ADD SI,0FEh ; make room for stack + MOV exec_init_SP,SI ; max value for read is also SP! + MOV exec_init_SS,AX + MOV DS,AX + MOV WORD PTR [SI],0 ; 0 for return + +exec_set_PDB: + MOV BX,exec_fh ; we are finished with the file. + CALL exec_dealloc + PUSH BP + invoke $CLOSE ; release the jfn + POP BP + CALL exec_alloc + TEST BYTE PTR exec_func,exec_func_overlay + JZ exec_build_header + CALL Scan_Execname ;MS.;AN007; + CALL Scan_Special_Entries ;MS.;AN007; + Leave + transfer SYS_RET_OK ; overlay load -> done + +exec_build_header: + MOV DX,exec_load_block +; +; assign the space to the process +; + + MOV SI,arena_owner ; pointer to owner field + + MOV AX,exec_environ ; get environ pointer + OR AX,AX + JZ NO_OWNER ; no environment + DEC AX ; point to header + MOV DS,AX + MOV [SI],DX ; assign ownership +NO_OWNER: + MOV AX,exec_load_block ; get load block pointer + DEC AX + MOV DS,AX ; point to header + MOV [SI],DX ; assign ownership + + PUSH DS ;AN000;MS. make ES=DS + POP ES ;AN000;MS. + MOV DI,ARENA_NAME ;AN000;MS. ES:DI points to destination + CALL Scan_Execname ;AN007;MS. parse execname + ; ds:si->name, cx=name length + PUSH CX ;AN007;;MS. save for fake version + PUSH SI ;AN007;;MS. save for fake version + +movename: ;AN000; + LODSB ;AN000;;MS. get char + CMP AL,'.' ;AN000;;MS. is '.' ,may be name.exe + JZ mem_done ;AN000;;MS. no, move to header + ;AN000; + STOSB ;AN000;;MS. move char + LOOP movename ;AN000;;MS. continue +mem_done: ;AN000; + XOR AL,AL ;AN000;;MS. make ASCIIZ + CMP DI,SIZE ARENA ;AN000;MS. if not all filled + JAE fill8 ;AN000;MS. + STOSB ;AN000;MS. +fill8: ;AN000; + POP SI ;AN007;MS. ds:si -> file name + POP CX ;AN007;MS. + + CALL Scan_Special_Entries ;AN007;MS. + + PUSH DX + MOV SI,exec_size + ADD SI,DX + invoke $Dup_PDB ; ES is now PDB + POP DX + + PUSH exec_environ + POP ES:[PDB_environ] +; +; set up proper command line stuff +; + LDS SI,exec_blk ; get the block + PUSH DS ; save its location + PUSH SI + LDS SI,[SI.exec0_5C_FCB] ; get the 5c fcb +; +; DS points to user space 5C FCB +; + MOV CX,12 ; copy drive, name and ext + PUSH CX + MOV DI,5Ch + MOV BL,[SI] + REP MOVSB +; +; DI = 5Ch + 12 = 5Ch + 0Ch = 68h +; + XOR AX,AX ; zero extent, etc for CPM + STOSW + STOSW +; +; DI = 5Ch + 12 + 4 = 5Ch + 10h = 6Ch +; + POP CX + POP SI ; get block + POP DS + PUSH DS ; save (again) + PUSH SI + LDS SI,[SI.exec0_6C_FCB] ; get 6C FCB +; +; DS points to user space 6C FCB +; + MOV BH,[SI] ; do same as above + REP MOVSB + STOSW + STOSW + POP SI ; get block (last time) + POP DS + LDS SI,[SI.exec0_com_line] ; command line +; +; DS points to user space 80 command line +; + OR CL,80h + MOV DI,CX + REP MOVSB ; Wham! +; +; Process BX into default AX (validity of drive specs on args). We no longer +; care about DS:SI. +; + DEC CL ; get 0FFh in CL + MOV AL,BH + XOR BH,BH + invoke GetVisDrv + JNC exec_BL + MOV BH,CL +exec_BL: + MOV AL,BL + XOR BL,BL + invoke GetVisDrv + JNC exec_Set_Return + MOV BL,CL +exec_set_return: + invoke get_user_stack ; get his return address + PUSH [SI.user_CS] ; suck out the CS and IP + PUSH [SI.user_IP] + PUSH [SI.user_CS] ; suck out the CS and IP + PUSH [SI.user_IP] + POP WORD PTR ES:[PDB_Exit] + POP WORD PTR ES:[PDB_Exit+2] + XOR AX,AX + MOV DS,AX + POP DS:[addr_int_terminate] ; save them where we can get them later + POP DS:[addr_int_terminate+2] ; when the child exits. + MOV WORD PTR DMAADD,80h + MOV DS,CurrentPDB + MOV WORD PTR DMAADD+2,DS + TEST BYTE PTR exec_func,exec_func_no_execute + JZ exec_go + + LDS SI,DWORD PTR exec_init_SP ; get stack + LES DI,exec_blk ; and block for return + MOV ES:[DI].exec1_SS,DS ; return SS + + DEC SI ; 'push' default AX + DEC SI + MOV [SI],BX ; save default AX reg + MOV ES:[DI].exec1_SP,SI ; return 'SP' + + LDS AX,DWORD PTR exec_init_IP + MOV ES:[DI].exec1_CS,DS ; initial entry stuff + + MOV ES:[DI].exec1_IP,AX + Leave + transfer SYS_RET_OK + +exec_go: + LDS SI,DWORD PTR exec_init_IP ; get entry point + LES DI,DWORD PTR exec_init_SP ; new stack + MOV AX,ES +; +; DS:SI points to entry point +; AX:DI points to initial stack +; DX has PDB pointer +; BX has initial AX value +; + CLI + MOV BYTE PTR INDOS,0 + ASSUME SS:NOTHING + MOV SS,AX ; set up user's stack + MOV SP,DI ; and SP + STI + PUSH DS ; fake long call to entry + PUSH SI + MOV ES,DX ; set up proper seg registers + MOV DS,DX + MOV AX,BX ; set up proper AX +procedure exec_long_ret,FAR + +IF BUFFERFLAG + invoke restore_user_map +ENDIF + + RET +EndProc exec_long_ret + +EndProc $Exec + +Procedure ExecRead,NEAR + CALL exec_dealloc + MOV bx,exec_fh + PUSH BP + invoke $READ + POP BP + CALL exec_alloc + return +EndProc ExecRead + +procedure exec_dealloc,near + ASSUME DS:NOTHING,ES:NOTHING + PUSH BX + MOV BX,arena_owner_system + EnterCrit CritMEM + CALL ChangeOwners + POP BX + return +EndProc exec_dealloc + +procedure exec_alloc,near + PUSH BX + MOV BX,CurrentPDB + CALL ChangeOwners + LeaveCrit CritMEM + POP BX + return +EndProc exec_alloc + +procedure ChangeOwners,NEAR + pushf + PUSH AX + MOV AX,exec_environ + CALL ChangeOwner + MOV AX,exec_load_block + Call ChangeOwner + POP AX + popf + return +EndProc ChangeOwners + +Procedure ChangeOwner,near + OR AX,AX ; is area allocated? + retz ; no, do nothing + DEC AX + PUSH DS + MOV DS,AX + MOV DS:[arena_owner],BX + POP DS + return +EndProc ChangeOwner + +Procedure Scan_Execname,near ;AN000;MS. + + LDS SI,execName ;AN000;MS. DS:SI points to name +save_begin: ;AN000; + MOV CX,SI ;AN000;MS. CX= starting addr +scan0: ;AN000; + LODSB ;AN000;MS. get char + CMP AL,':' ;AN000;;MS. is ':' , may be A:name + JZ save_begin ;AN000;;MS. yes, save si + CMP AL,'\' ;AN000;;MS. is '\', may be A:\name + JZ save_begin ;AN000;;MS. yes, save si + CMP AL,0 ;AN000;;MS. is end of name + JNZ scan0 ;AN000;;MS. no, continue scanning + SUB SI,CX ;AN000;;MS. get name's length + XCHG SI,CX ;AN000;;MS. cx= length, si= starting addr + + return ;AN000;;MS. +EndProc Scan_Execname ;AN000;;MS. + + +Procedure Scan_Special_Entries,near ;AN000;MS. + + DEC CX ;AN007;MS. cx= name length + MOV DI,CS:[Special_Entries] ;AN007;MS. es:di -> addr of special entries + CALL Reset_Version ;AN008;MS. + PUSH CS ;AN007;MS. + POP ES ;AN007;MS. +Getentries: ;AN007;MS. + MOV AL,ES:[DI] ;AN007;MS. end of list + OR AL,AL ;AN007;MS. + JZ end_list ;AN007;MS. yes + MOV CS:[Temp_Var2],DI ;AN007;MS. save di + CMP AL,CL ;AN007;MS. same length ? + JNZ skipone ;AN007;MS. no + INC DI ;AN007;MS. es:di -> special name + PUSH CX ;AN007;MS. save length and name addr + PUSH SI ;AN007;MS. + REPZ CMPSB ;AN007;MS. same name ? + JNZ not_matched ;AN007;MS. no + MOV AX,ES:[DI] ;AN007;MS. get special version + MOV CS:[Special_Version],AX ;AN007;MS. save it + MOV AL,ES:[DI+2] ;AN008;MS. get fake count + MOV CS:[Fake_Count],AL ;AN007;MS. save it + POP SI ;AN007;MS. + POP CX ;AN007;MS. + JMP SHORT end_list ;AN007;MS. +not_matched: ;AN007;MS. + POP SI ;AN007;MS. restore si,cx + POP CX ;AN007;MS. +skipone: ;AN007;MS. + MOV DI,CS:[Temp_Var2] ;AN007;MS. restore old di + XOR AH,AH ;AN007;MS. position to next entry + ADD DI,AX ;AN007;MS. + ADD DI,4 ;AN007;MS. + JMP Getentries ;AN007;MS. + + +end_list: ;AN007;MS. + return +EndProc Scan_Special_Entries ;AN000;;MS. + +Procedure Reset_Version,near ;AN008;MS. + + CMP CS:[Fake_Count],0FFH ;AN008;MS. + JNZ dont_reset ;AN008;MS. + MOV CS:[Special_Version],0 ;AN008;MS. reset to current version +dont_reset: + return +EndProc Reset_Version,near ;AN008;;MS. + \ No newline at end of file diff --git a/v4.0/src/DOS/EXTATTR.ASM b/v4.0/src/DOS/EXTATTR.ASM new file mode 100644 index 0000000..1cc1d32 --- /dev/null +++ b/v4.0/src/DOS/EXTATTR.ASM @@ -0,0 +1,679 @@ +TITLE EXTATTR- Extended Attributes +NAME EXTATTR +; +; Get or Set Extended Attributes by handle +; +; +; GetSetEA +; Set_Output +; Search_EA +; Copy_QEA +; Set_one_EA +; Get_one_EA +; Get_Value +; GSetDevCdpg +; Get_max_EA_size +; +; Revision history +; +; A000 version 4.00 Jan. 1988 +; +; +; +; +; +; +; + +.xlist +; +; +; get the appropriate segment definitions +; +include dosseg.asm ;AN000; + +CODE SEGMENT BYTE PUBLIC 'CODE' ;AN000; + ASSUME SS:DOSGROUP,CS:DOSGROUP ;AN000; + +.xcref +INCLUDE DOSSYM.INC ;AN000; +INCLUDE DEVSYM.INC ;AN000; +include EA.inc ;AN000; +.cref +.list +.sall + + +; I_need XA_from,BYTE ;AN000; + +; I_need XA_TABLE,BYTE ;AN000; +; I_need XA_TEMP,WORD ;AN000; +; I_need XA_COUNT,WORD ;AN000; +; I_need XA_DEVICE,BYTE ;AN000; + I_need XA_TYPE,BYTE ;AN000; + I_need SAVE_ES,WORD ;AN000; + I_need SAVE_DI,WORD ;AN000; + I_need SAVE_DS,WORD ;AN000; + I_need SAVE_SI,WORD ;AN000; + I_need SAVE_CX,WORD ;AN000; + I_need SAVE_BX,WORD ;AN000; +; I_need XA_handle,WORD ;AN000; +; I_need CPSWFLAG,BYTE ;AN000; +; I_need XA_PACKET,BYTE ;AN000; +; I_need MAX_EA_SIZE,WORD ;AN000; +; I_need MAX_EANAME_SIZE,WORD ;AN000; +; I_need THISSFT,DWORD ;AN000; +;IF DBCS ;AN000; +; I_need DBCS_PACKET,BYTE ;AN000; ;AN000; +;ENDIF ;AN000; ;AN000; + ;AN000; + ;AN000; + ;AN000; + ;AN000; + ;AN000; +BREAK ;AN000; + ;AN000; +; Input: [XA_type] = function code, (e.g., get,set) ;AN000; +; [ThisSFT] points to SFT ;AN000; +; ES:BP points to drive parameter block ;AN000; +; [XA_from] = By_Create or By_EA ;AN000; +; [SAVE_ES]:[SAVE_DI] points to get/set list ;AN000; +; [SAVE_DS]:[SAVE_SI] points to get query list ;AN000; +; [SAVE_CX] = size of buffer +; [XA_device]= 1 device, 0 file ;AN000; +; [XA_handle] for device ;AN000; +; Function: Get or Set extended attributes by handle ;AN000; +; Output: carry set: error ;AN000; +; carry clear: extended attributes are successfully get/set ;AN000; +; extended attribute cluster may be created ;AN000; +; ;AN000; +; ;AN000; +; ;AN000; + ;AN000; + ;AN000; +procedure GetSet_XA,near ;AN000; + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP ;AN000; + + + LES DI,DWORD PTR [SAVE_DI] ;AN000;;FT. ES:DI -> query list +;; MOV [SAVE_BX],2 ;AN000;;FT. size returned +;; XOR DX,DX ;AN000;;FT. dx=0, codepage id + + CMP [XA_type],2 ;AN000;;FT. get EA ? + JNZ eaname ;AN000;;FT. no +getEAs: ;AN000; + CMP [SAVE_CX],0 ;AN000;;FT. get max data size + JNZ notmax ;AN000;;FT. no +;; CALL Get_max_EA_size ;AN000;;FT. + + MOV CX,2 ;AN000;;FT. FAKE FAKE.............. + JNC set_user_cx ;AN000;;FT. + JMP OKexit ;AN000;;FT. error +notmax: + CMP [SAVE_CX],1 ;AN000;;FT. buffer size =1 ? + JNZ goodsiz ;AN000;;FT. no +errout: ;AN000; + JMP insuff_space ;AN000;;FT. no error +goodsiz: ;AN000; + MOV WORD PTR ES:[DI],0 ;AN000;FT. FAKE FAKE ............... + MOV CX,2 ;AN000;FT. FAKE FAKE ............... + JMP set_user_cx ;AN000;FT. FAKE FAKE ............... + +; SUB [SAVE_CX],2 ;AN000;;FT. minus count size +; CMP [SAVE_SI],-1 ;AN000;;FT. get all ? +; JNZ getsome ;AN000;;FT. no +; PUSH CS ;AN000;;FT. ds:si-> EA entry addr +; POP DS ;AN000;;FT. +; INC DI ;AN000;;FT. +; INC DI ;AN000;;FT. es:di -> address after count +; MOV SI,OFFSET DOSGROUP:XA_TABLE ;AN000;FT. +; MOV CX,XA_COUNT ;AN000;;FT. cx= number of EA entries +;;;;;; +;getone: +; CALL GET_ONE_EA ;AN000;;FT. get EA +; JC setout ;AN000;;FT. insufficient memory +; INC DX ;AN000;;FT. next EA ID +; LOOP getone ;AN000;;FT. next one +;setout: ;AN000; +; CALL Set_Output ;AN000;;FT. +; OR CX,CX ;AN000;;FT. +; JNZ errout ;AN000;;FT. +; +; JMP OKexit ;AN000;;FT. +eaname: + CMP [XA_type],3 ;AN000;;FT. get EA name?` + JZ geteaname ;AN000;;FT. yes + JMP setea ;AN000;;FT. +geteaname: +; MOV [SAVE_SI],-1 ;AN000;;FT. make get all + CMP [SAVE_CX],0 ;AN000;;FT. get max data size + JNZ notmax ;AN000;;FT. no + MOV CX,2 ;AN000;;FT. FAKE FAKE ...................... +;; MOV CX,[MAX_EANAME_SIZE] ;AN000;;FT. get name size +set_user_cx: ;AN000; + invoke get_user_stack ;AN000;;FT. get user stack + MOV [SI.user_CX],CX ;AN000;;FT. + JMP OKexit ;AN000;;FT. exit + +getsome: ;AN000; +; LDS SI,DWORD PTR [SAVE_SI] ;AN000;;FT. +; LODSW ;AN000;;FT. +; MOV CX,AX ;AN000;;FT. cx=number of query entries +; JCXZ setout ;AN000;;FT. yes +; STOSW ;AN000;;FT. es:di -> EA +;get_next_EA: ;AN000; +; PUSH DS ;AN000;;FT. save ds:si +; PUSH SI ;AN000;;FT. es:di +; PUSH ES ;AN000;;FT. +; PUSH DI ;AN000;;FT. +; CALL Search_EA ;AN000;;FT. search query EA from table +; JC EAnotFound ;AN000;;FT. EA not found +; PUSH ES ;AN000;;FT. +; POP DS ;AN000;;FT. +; MOV SI,DI ;AN000;;FT. ds:si -> found EA +; POP DI ;AN000;;FT. es:di -> buffer +; POP ES ;AN000;;FT. +; CALL GET_ONE_EA ;AN000;;FT. copy to buffer +; POP SI ;AN000;;FT. +; POP DS ;AN000;;FT. +; JC setfinal ;AN000;;FT. memory not enough +; MOV AL,[SI.QEA_NAMELEN] ;AN000;;FT. +; XOR AH,AH ;AN000;;FT. +; ADD AX,QEA_NAME ;AN000;;FT. +; ADD SI,AX ;AN000;;FT. ds:si -> next query entry +;testend: ;AN000; +; LOOP get_next_EA ;AN000;;FT. do next +;setfinal: ;AN000; +; LDS SI,DWORD PTR [SAVE_SI] ;AN000;;FT. +; MOV DX,[SI] ;AN000;;FT. +; SUB DX,CX ;AN000;;FT. dx= returned count +; JMP setout ;AN000;;FT. +;EAnotFound: ;AN000; +; POP DI ;AN000;;FT. restore regs +; POP ES ;AN000;;FT. +; POP SI ;AN000;;FT. +; POP DS ;AN000;;FT. +; +; CALL COPY_QEA ;AN000;;FT. copy query EA to buffer +; JC setfinal ;AN000;;FT. not enough memory +; JMP testend ;AN000;;FT. +setea: ;AN000; + JMP OKexit ;AN000;;FT. FAKE FAKE .......... +; LDS SI,DWORD PTR [SAVE_DI] ;AN000;;FT. +; LODSW ;AN000;;FT. +; MOV CX,AX ;AN000;;FT. cx=number of query entries +; OR CX,CX ;AN000;;FT. cx=0 ? +; JZ OKexit ;AN000;;FT. yes +;set_next: ;AN000; +; CALL Search_EA ;AN000;;FT. +; JNC toset ;AN000;;FT. +;set_reason: ;AN000; +; CLC ;AN000;;FT. clear acrry +; MOV [SI.EA_RC],AL ;AN000;;FT. set reason code +; DEC CX ;AN000;;FT. end of set ? +; JZ OKexit ;AN000;;FT. yes + +; MOV AL,[SI.EA_NAMELEN] ;AN000;;FT. +; XOR AH,AH ;AN000;;FT. +; ADD AX,[SI.EA_VALLEN] ;AN000;;FT. +; ADD SI,EA_NAME ;AN000;;FT. +; ADD SI,AX ;AN000;;FT. es:di -> next EA entry +; JMP set_next ;AN000;;FT. +;toset: ;AN000; +; CALL SET_ONE_EA ;AN000;;FT. set it +; JMP set_reason ;AN000;;FT. + insuff_space: ;AN000;;FT. +; MOV AX,error_not_enough_memory ;AN000;FT. insufficient memory err +; STC ;AN000; +OKexit: ;AN000; + return ;AN000; + +EndProc GetSet_XA ;AN000; + + +; Input: [SAVE_ES]:[SAVE_DI] points to buffer +; [SAVE_BX]= returned size +; DX= returned count +; Function: set returned size and count ;AN000; +; Output: none + ;AN000; +;procedure Set_Output,NEAR ;AN000; +; ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP ;AN000; +; ;AN000; +; LES DI,DWORD PTR [SAVE_DI] ;FT. es:di -> count ;AN000; +; MOV ES:[DI],DX ;FT. ;AN000; +; MOV BX,[SAVE_BX] ;FT. cx=size returned ;AN000; +; invoke get_user_stack ;FT. get user stack ;AN000; +; MOV [SI.user_CX],BX ;FT. ;AN000; +; return ;FT. ;AN000; +; ;AN000; +;EndProc Set_Output ;AN000; + + +; Input: DS:SI= query EA addr ;AN000; +; Function: search the EA ;AN000; +; Output: carry clear +; DX= EA ID (0 codpage, 1 Filetype, etc.) +; ES:DI points to found entry +; carry set, not found, AL= reason code ;AN000; + ;AN000; +;procedure Search_EA,NEAR ;AN000; +; ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP ;AN000; +; ;AN000; +; PUSH CX ;FT. save entry count ;AN000; +; MOV AL,EARCNOTFOUND ;FT. preset error code ;AN000; +; MOV BL,[SI.QEA_NAMELEN] ;FT. ? ;AN000; +; CMP [XA_TYPE],4 ;FT. set ? ;AN000; +; JNZ gettyp ;FT. no ;AN000; +; MOV BL,[SI.EA_NAMELEN] ;FT. ? ;AN000; +;gettyp: +; OR BL,BL ;FT. ;AN000; +; JZ not_found ;FT. ;AN000; +; PUSH CS ;FT. ds:si-> EA entry addr ;AN000; +; POP ES ;FT. ;AN000; +; MOV DI,OFFSET DOSGROUP:XA_TABLE ;FT. ;AN000; +; MOV CX,XA_COUNT ;FT. cx= number of EA entries ;AN000; +; XOR DX,DX ;FT. dx=0, codepage id ;AN000; +; +;start_find: +; PUSH CX ;FT. save entry count ;AN000; +; MOV CL,BL ;FT. ;AN000; +; XOR CH,CH ;FT. get name len ;AN000; +; PUSH SI ;FT. ;AN000; +; PUSH DI ;FT. ;AN000; +; CMP [XA_TYPE],4 ;FT. set ? ;AN000; +; JNZ gettyp2 ;FT. no ;AN000; +; ADD SI,EA_NAME ;FT. ;AN000; +; JMP short updi ;FT. ;AN000; +;gettyp2: +; ADD SI,QEA_NAME ;FT. compare EA names ;AN000; +;updi: +; ADD DI,EA_NAME ;FT. ;AN000; +; REP CMPSB ;FT. ;AN000; +; POP DI ;FT. ;AN000; +; POP SI ;FT. ;AN000; +; POP CX ;FT. ;AN000; +; JNZ not_matched ;FT. name not matched ;AN000; +; MOV AL,EARCDEFBAD ;FT. preset error code ;AN000; +; PUSH SI ;FT. ;AN000; +; PUSH DI ;FT. ;AN000; +; CMPSB ;FT. compare type ;AN000; +; JNZ not_matched2 ;FT. type not matched ;AN000; +; CMPSW ;FT. compare flags ;AN000; +; JNZ not_matched2 ;FT. flag not matched ;AN000; +; POP DI ;FT. ;AN000; +; POP SI ;FT. found one ;AN000; +; JMP SHORT found_one ;FT. ;AN000; +;not_matched: +; DEC CX ;FT. end of table ;AN000; +; JZ not_found ;FT. yes ;AN000; +; MOV AL,ES:[DI.EA_NAMELEN] ;FT. ;AN000; +; XOR AH,AH ;FT. ;AN000; +; +; ADD DI,EA_NAME ;FT. ;AN000; +; ADD DI,AX ;FT. es:di -> next EA entry ;AN000; +; INC DX ;FT. increment EA ID ;AN000; +; JMP start_find ;FT. ;AN000; +;not_matched2: +; POP DI ;FT. ;AN000; +; POP SI ;FT. ;AN000; +; JMP not_matched ;FT. ;AN000; +;not_found: +; STC ;FT. ;AN000; +;found_one: +; POP CX ;FT. ;AN000; +; return ;FT. ;AN000; + ;AN000; +;EndProc Search_EA ;AN000; + ;AN000; +; Input: ES:DI= buffer address ;AN000; +; DS:SI= EA entry address +; [SAVE_CX]= buffer size +; AL = reason code +; Function: move one query entry to buffer ;AN000; +; Output: carry clear +; DS:SI points to next entry +; ES:DI points to next entry +; [SAVE_CX],[SAVE_BX], updated ;AN000; +; carry set, insufficient memory error ;AN000; + ;AN000; +;procedure COPY_QEA,NEAR ;AN000; +; ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP ;AN000; +; ;AN000; +; PUSH CX ;FT. ;AN000; +; MOV DL,AL ;FT. ;AN000; +; MOV CX,EA_NAME -EA_TYPE ;FT. ;AN000; +; +; MOV BL,[SI.QEA_NAMELEN] ;FT. ;AN000; +; XOR BH,BH ;FT. ;AN000; +; ADD CX,BX ;FT. cx= query EA size ;AN000; +; CMP CX,[SAVE_CX] ;FT. > buffer size ;AN000; +; JA sizeshort2 ;FT. yes ;AN000; +; PUSH CX ;FT. ;AN000; +; LODSB ;FT. move type ;AN000; +; STOSB ;FT. ;AN000; +; LODSW ;FT. ;AN000; +; STOSW ;FT. move flag ;AN000; +; MOV AL,DL ;FT. move RC ;AN000; +; STOSB ;FT. ;AN000; +; +; LODSB ;FT. move name len ;AN000; +; MOV CL,AL ;FT. ;AN000; +; STOSB ;FT. ;AN000; +; XOR AX,AX ;FT. zero value length ;AN000; +; STOSW ;FT. ;AN000; +; OR CL,CL ;FT. ;AN000; +; JZ zeroname ;FT. ;AN000; +; XOR CH,CH ;FT. ;AN000; +; +; REP MOVSB ;FT. move EA to buffer ;AN000; +;zeroname: +; POP CX ;FT. ;AN000; +; ADD [SAVE_BX],CX ;FT. bx=bx+entry size ;AN000; +; SUB [SAVE_CX],CX ;FT. update buffer size ;AN000; +; CLC ;FT. ;AN000; +; JMP SHORT okget2 ;FT. ;AN000; +; +;sizeshort2: +; MOV AX,error_not_enough_memory ;FT. error ;AN000; +; STC ;FT. ;AN000; +;okget2: +; POP CX ;FT. ;AN000; +; return ;FT. ;AN000; +; ;AN000; +;EndProc COPY_QEA ;AN000; + ;AN000; +; Input: ES:DI= found EA entry addr ;AN000; +; DS:SI= source EA entry address +; DX= EA ID (0 codpage, 1 Filetype, etc.) +; Function: set one EA ;AN000; +; Output: carry clear +; EA set +; carry set, AL= reason code ;AN000; + ;AN000; +;procedure SET_ONE_EA,NEAR ;AN000; +; ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP ;AN000; +; ;AN000; +; PUSH CX ;FT. ;AN000; +; MOV AL,EARCDEFBAD ;FT. prseet error code ;AN000; +; MOV BX,[SI.EA_VALLEN] ;FT. ;AN000; +; CMP BX,ES:[DI.EA_VALLEN] ;FT. length equal ? ;AN000; +; JNZ notset ;FT. no ;AN000; +; PUSH DS ;FT. ;AN000; +; PUSH SI ;FT. ;AN000; +; MOV AL,[SI.EA_NAMELEN] ;FT. ;AN000; +; XOR AH,AH ;FT. ;AN000; +; ADD SI,EA_NAME ;FT. ;AN000; +; ADD SI,AX ;FT. ;AN000; +; CMP DX,0 ;FT. ;AN000; +; JNZ set_filetyp ;FT. ;AN000; +; LODSW ;FT. ;AN000; +; CMP [XA_DEVICE],0 ;FT. device ? ;AN000; +; JZ notdevice ;FT. no ;AN000; +; OR AX,AX ;FT. code page 0 ? ;AN000; +; JZ NORM0 ;FT. yes ;AN000; +; +; CALL GSetDevCdPg ;FT. ;AN000; +; JNC welldone ;FT. ;AN000; +; CMP [CPSWFLAG],0 ;FT. code page matching on ;AN000; +; JZ NORM0 ;FT. no ;AN000; +; invoke SAVE_WORLD ;FT. save all regs ;AN000; +; LDS SI,[THISSFT] ;FT. ds:si -> sft ;AN000; +; LDS SI,[SI.sf_devptr] ;FT. ds:si -> device header ;AN000; +; MOV BP,DS ;FT. save all regs ;AN000; +; invoke Code_Page_Mismatched_Error ;FT. ;AN000; +; CMP AL,0 ;FT. ignore ? ;AN000; +; JZ NORM1 ;FT. ;AN000; +; invoke RESTORE_WORLD ;FT. save all regs ;AN000; +;NORM0: +; MOV AL,EARCDEVERROR ;FT. ;AN000; +; STC ;FT. ;AN000; +; JMP SHORT sdone ;FT. ;AN000; +;NORM1: +; invoke RESTORE_WORLD ;FT. save all regs ;AN000; +; JMP SHORT welldone ;FT. ;AN000; +;notdevice: +; LDS SI,[THISSFT] ;FT. ;AN000; +; MOV [SI.sf_CodePage],AX ;FT. set codepege ;AN000; +; JMP SHORT welldone ;FT. +;set_filetyp: +; LODSB ;FT. ;AN000; +; LDS SI,[THISSFT] ;FT. set filtype ;AN000; +; MOV [SI.sf_ATTR_HI],AL ;FT. ;AN000; +; +;welldone: +; XOR AL,AL ;FT. success ;AN000; +;sdone: +; POP SI ;FT. ;AN000; +; POP DS ;FT. ;AN000; +;notset: +; POP CX ;FT. ;AN000; +; return ;FT. ;AN000; + ;AN000; +;EndProc SET_ONE_EA ;AN000; + ;AN000; +; Input: ES:DI= buffer address ;AN000; +; DS:SI= EA entry address +; [SAVE_CX]= buffer size available +; [SAVE_BX]= size returned +; DX= EA ID (0 codpage, 1 Filetype, etc.) +; Function: move one EA entry to the buffer ;AN000; +; Output: carry clear +; DS:SI points to next entry +; ES:DI points to next entry +; [SAVE_CX],BX, updated ;AN000; +; carry set, insufficient memory error ;AN000; + ;AN000; +;procedure GET_ONE_EA,NEAR ;AN000; +; ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP ;AN000; +; ;AN000; +; PUSH CX ;FT. ;AN000; +; CMP [XA_TYPE],2 ;FT. type 2 ? ;AN000; +; JZ gtyp2 ;FT. yes ;AN000; +; MOV CX,QEA_NAME - QEA_TYPE ;FT. ;AN000; +; JMP SHORT addnmlen ;FT. +;gtyp2: +; MOV CX,EA_NAME - EA_TYPE ;FT. cx = EA entry size ;AN000; +; ADD CX,[SI.EA_VALLEN] ;FT. ;AN000; +;addnmlen: +; MOV AL,[SI.EA_NAMELEN] ;FT. +; XOR AH,AH ;FT. ;AN000; +; ADD CX,AX ;FT. ;AN000; +; CMP CX,[SAVE_CX] ;FT. > buffer size ;AN000; +; JA sizeshort ;FT. yes ;AN000; +; PUSH CX ;FT. ;AN000; +; LODSB ;FT. move type ;AN000; +; STOSB ;FT. ;AN000; +; LODSW ;FT. ;AN000; +; STOSW ;FT. move flag ;AN000; +; LODSB ;FT. EA list need RC ;AN000; +; CMP [XA_TYPE],2 ;FT. ;AN000; +; JNZ norc ;FT. ;AN000; +; STOSB ;FT. ;AN000; +;norc: +; LODSB ;FT. move name len ;AN000; +; STOSB ;FT. ;AN000; +; MOV CL,AL ;FT. ;AN000; +; XOR CH,CH ;FT. ;AN000; +; LODSW ;FT. EA list need value len ;AN000; +; CMP [XA_TYPE],2 ;FT. ;AN000; +; JNZ novalen ;FT. ;AN000; +; STOSW ;FT. ;AN000; +;novalen: +; +; REP MOVSB ;FT. move EA to buffer ;AN000; +; CMP [XA_TYPE],2 ;FT. ;AN000; +; JNZ novalue ;FT. ;AN000; +; CALL GET_VALUE ;FT. get value for type 2 ;AN000; +;novalue: +; POP CX ;FT. ;AN000; +; ADD [SAVE_BX],CX ;FT. add entry size ;AN000; +; LES DI,DWORD PTR [SAVE_DI] ;FT. ;AN000; +; ADD DI,[SAVE_BX] ;FT. es:di -> next entry ;AN000; +; SUB [SAVE_CX],CX ;FT. update buffer size ;AN000; +; CLC ;FT. ;AN000; +; JMP SHORT okget ;FT. ;AN000; +; +;sizeshort: +; MOV AX,error_not_enough_memory ;FT. error ;AN000; +; STC ;FT. ;AN000; +;okget: +; POP CX ;FT. ;AN000; +; return ;FT. ;AN000; +; ;AN000; +;EndProc GET_ONE_EA ;AN000; + ;AN000; + ;AN000; +; Input: DX= EA ID (0 codpage, 1 Filetype, etc.) +; [THISSFT]= points to SFT +; ES:DI= buffer address of EA value +; [XA_DEVICE]=0 file, 1 device +; Function: get attribute ;AN000; +; Output: none ;AN000; +; ;AN000; + ;AN000; +;procedure GET_VALUE,NEAR ;AN000; +; ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP ;AN000; +; ;AN000; +; PUSH DS ;FT. save ds:si ;AN000; +; PUSH SI ;FT. ;AN000; +; LDS SI,[ThisSFT] ;FT. ds:si -> SFT ;AN000; +; +; CMP DX,0 ;FT. code page ? ;AN000; +; JNZ eafiltyp ;FT. no ;AN000; +; CMP [XA_DEVICE],0 ;FT. device ? ;AN000; +; JZ notdev ;FT. no ;AN000; +; CALL GSetDevCdPg ;FT. do ioctl invoke ;AN000; +; JNC okcdpg ;FT. error ? ;AN000; +; PUSH DI ;FT. ;AN000; +; XOR AX,AX ;FT. make code page 0 ;AN000; +; LES DI,DWORD PTR [SAVE_DI] ;FT. ;AN000; +; ADD DI,[SAVE_BX] ;FT. es:di -> beginning of entry ;AN000; +; MOV ES:[DI.EA_RC],EARCNOTFOUND ;FT. ;AN000; +; POP DI ;FT. ;AN000; +; JMP SHORT okcdpg ;FT. ;AN000; +;notdev: +; MOV AX,[SI.sf_CodePage] ;FT. get code page from sft ;AN000; +;okcdpg: +; STOSW ;FT. put in buffer ;AN000; +; JMP SHORT gotea ;FT. ;AN000; +;eafiltyp: +; MOV AL,[SI.sf_ATTR_HI] ;FT. get high attribute ;AN000; +; STOSB ;FT. put in buffer ;AN000; +; +;gotea: +; POP SI ;FT. retore regs ;AN000; +; POP DS ;FT. ;AN000; +; return ;FT. ;AN000; +;EndProc GET_VALUE ;AN000; + ;AN000; + ;AN000; +; Input: [XA_handle] = device handle ;AN000; +; [XA_type] = 4 , set ;AN000; +; AX= code page (set) +; 2,3 get ;AN000; +; Function: get or set device code page ;AN000; +; Output: carry clear, AX= device code page (get) ;AN000; +; carry set, error ;AN000; + ;AN000; +;procedure GSetDevCdPg,near ;AN000; +; ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP ;AN000; +; ;AN000; +; invoke SAVE_WORLD ;FT. save all regs ;AN000; +; CMP [XA_type],4 ;FT. set ? ;AN000; +; JZ setpg ;FT. yes ;AN000; +; MOV CX,6AH ;FT. get selected code page ;AN000; +; JMP SHORT dogset ;FT. ;AN000; +;setpg: ;AN000; +; MOV CX,4AH ;FT. set code page ;AN000; +;IF DBCS +; +; invoke Save_World ;FT. save all regs ;AN000; +; MOV BX,AX ;FT. bx= code page id ;AN000; +; MOV AL,7 ;FT. get DBCS vectors ;AN000; +; MOV DX,-1 ;FT. get current country ;AN000; +; MOV CX,5 ;FT. minimum size ;AN000; +; MOV DI,OFFSET DOSGROUP:DBCS_PACKET ;FT. ;AN000; +; PUSH CS ;FT. ;AN000; +; POP ES ;FT. ;AN000; +; invoke $GetExtCntry ;FT. get DBCS vectors ;AN000; +; JC nlsfunc_err ;FT. error ;AN000; +; LDS SI,DWORD PTR DBCS_PACKET+1 ;FT. ;AN000; +; LODSW ;FT. get vector length ;AN000; +; MOV CX,AX ;FT. cx=length ;AN000; +; +; MOV DI,OFFSET DOSGROUP:XA_PACKET+4 ;FT. ;AN000; +; PUSH CS ;FT. ;AN000; +; POP ES ;FT. ;AN000; +; REP MOVSB ;FT. ;AN000; +; CLC ;FT. ;AN000; +;nlsfunc_err: +; invoke RESTORE_WORLD ;FT. restore all regs ;AN000; +; JC deverr ;FT. ;AN000; +; +;ENDIF +; MOV WORD PTR [XA_PACKET+2],AX ;FT. ;AN000; +;dogset: ;AN000; +; MOV BX,[XA_handle] ;FT. set up handle ;AN000; +; PUSH CS ;FT. ds:dx -> packet ;AN000; +; POP DS ;FT. ;AN000; +; MOV DX,OFFSET DOSGROUP:XA_PACKET ;FT. ;AN000; +; MOV AX,440CH ;FT. IOCTL to char device by handle ;AN000; +; invoke $IOCTL ;FT. issue get code page ;AN000; +; JC deverr ;FT. error ;AN000; +; invoke RESTORE_WORLD ;FT. restore all regs ;AN000; +; MOV AX,WORD PTR [XA_PACKET+2] ;FT. get code page ;AN000; +; return ;FT. ;AN000; +;deverr: ;AN000; +; invoke RESTORE_WORLD ;FT. restore all regs ;AN000; +; return ;FT. exit ;AN000; +; ;AN000; +;EndProc GSetDevCdPg ;AN000; + ;AN000; + +; Input: DS:SI -> query list +; +; Function: get max size ;AN000; +; Output: CX= size +; carry set error + ;AN000; +;procedure Get_max_EA_size,NEAR ;AN000; +; ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP ;AN000; +; ;AN000; +; CMP [SAVE_SI],0FFFFH ;FT. get all ? ;AN000; +; JNZ scan_query ;FT. no ;AN000; +; MOV CX,[MAX_EA_SIZE] ;FT. get max EA size ;AN000; +; JMP SHORT gotit ;FT. +;scan_query: +; LDS SI,DWORD PTR [SAVE_SI] ;FT. ds:si -> query list ;AN000; +; LODSW ;FT. ax= number of entries ;AN000; +; MOV [SAVE_CX],AX ;FT. ;AN000; +; XOR CX,CX ;FT. set initial size to 0 ;AN000; +; OR AX,AX ;FT. if no entris ;AN000; +; JZ gotit ;FT. then return ;AN000; +; MOV CX,2 ;FT. at lesat 2 ;AN000; +;NEXT_QEA: +; CALL Search_EA ;FT. search EA ;AN000; +; JC serror ;FT. wrong EA ;AN000; +; ADD CX,size EA ;FT. get EA size ;AN000; +; ADD CL,ES:[DI.EA_NAMELEN] ;FT. ;AN000; +; ADC CH,0 ;FT. ;AN000; +; ADD CX,ES:[DI.EA_VALLEN] ;FT. ;AN000; +; DEC CX ;FT. ;AN000; +; DEC [SAVE_CX] ;FT. end of entris ;AN000; +; JZ gotit ;FT. no ;AN000; +; MOV AL,[SI.QEA_NAMELEN] ;FT. update to next QEA ;AN000; +; XOR AH,AH ;FT. update to next QEA ;AN000; +; ADD SI,AX ;FT. update to next QEA ;AN000; +; ADD SI,size QEA ;FT. ;AN000; +; DEC SI ;FT. ;AN000; +; JMP next_QEA ;FT. do next ;AN000; +;serror: +; MOV AX,error_invalid_data ;FT. set initial size to 0 ;AN000; +;gotit: ;FT. ;AN000; +; return ;FT. exit ;AN000;;FT. exit ;AN000; +; +;EndProc Get_max_EA_size ;FT. exit ;AN000; ;AN000; + ;AN000; +CODE ENDS ;AN000; +END ;AN000; diff --git a/v4.0/src/DOS/FAT.ASM b/v4.0/src/DOS/FAT.ASM new file mode 100644 index 0000000..971c427 --- /dev/null +++ b/v4.0/src/DOS/FAT.ASM @@ -0,0 +1,695 @@ +; SCCSID = @(#)fat.asm 1.3 85/08/15 +; SCCSID = @(#)fat.asm 1.3 85/08/15 +TITLE FAT - FAT maintenance routines +NAME FAT +; Low level local device routines for performing disk change sequence, +; setting cluster validity, and manipulating the FAT +; +; IsEof +; UNPACK +; PACK +; MAPCLUSTER +; FATREAD_SFT +; FATREAD_CDS +; FAT_operation +; +; Revision history: +; +; AN000 version Jan. 1988 +; A001 PTM -- disk changed for look ahead buffers +; + +; +; get the appropriate segment definitions +; +.xlist +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +.cref +.list + +FastDiv = TRUE + + i_need CURBUF,DWORD + i_need CLUSSPLIT,BYTE + i_need CLUSSAVE,WORD + i_need CLUSSEC,DWORD ;F.C. >32mb ;AN000; + i_need THISDRV,BYTE + i_need THISDPB,DWORD + i_need DEVCALL,BYTE + i_need CALLMED,BYTE + i_need CALLRBYT,BYTE + i_need BUFFHEAD,DWORD + i_need CALLXAD,DWORD + i_need CALLBPB,DWORD + i_need CDSADDR,DWORD + i_need CDSCOUNT,BYTE + i_need EXTERR,WORD + i_need EXTERRPT,DWORD + i_need CALLVIDM,DWORD + i_need ReadOp,BYTE + i_need FAILERR,BYTE + i_need ALLOWED,BYTE + i_need VOLCHNG_FLAG,BYTE + i_need HIGH_SECTOR,WORD + i_need BUF_HASH_COUNT,WORD + i_need BUF_HASH_PTR,DWORD + i_need FIRST_BUFF_ADDR,WORD + i_need SC_CACHE_COUNT,WORD ;AN001; + i_need CURSC_DRIVE,BYTE ;AN001; + + +Break + +; +; IsEOF - check the fat value in BX for eof. +; +; Inputs: ES:BP point to DPB +; BX has fat value +; Outputs: JAE eof +; Registers modified: none +Procedure IsEof,NEAR + ASSUME SS:DOSGROUP,CS:DOSGROUP,DS:NOTHING,ES:NOTHING + Assert ISDPB,,"IsEOF" + CMP ES:[BP.dpb_max_cluster],4096-10 ; is this 16 bit fat? + JAE EOF16 ; yes, check for eof there +;J.K. 8/27/86 +;Modified to accept 0FF0h as an eof. This is to handle the diskfull case +;of any media that has "F0"(Other) as a MediaByte. +;Hopely, this does not create any side effect for those who may use any value +;other than "FF8-FFF" as an Eof for their own file. + cmp bx,0FF0h + je IsEOF_other + CMP BX,0FF8h ; do the 12 bit compare +IsEOF_other: + return +EOF16: + CMP BX,0FFF8h ; 16 bit compare + return +EndProc IsEof + +Break + +; Inputs: +; BX = Cluster number (may be full 16-bit quantity) +; ES:BP = Base of drive parameters +; Outputs: +; DI = Contents of FAT for given cluster (may be full 16-bit quantity) +; Zero set means DI=0 (free cluster) +; Carry set means error (currently user FAILed to I 24) +; SI Destroyed, No other registers affected. Fatal error if cluster too big. + + procedure UNPACK,NEAR + DOSAssume CS,,"UnPack" + ASSUME ES:NOTHING + + Assert ISDPB,,"Unpack" + CMP BX,ES:[BP.dpb_max_cluster] + JA HURTFAT + CALL MAPCLUSTER +ASSUME DS:NOTHING + jc DoContext + MOV DI,[DI] + JNZ High12 ; MZ if high 12 bits, go get 'em + MOV SI,ES:[BP.dpb_max_cluster] ; MZ is this 16-bit fat? + CMP SI,4096-10 + JB Unpack12 ; MZ No, go 'AND' off bits + OR DI,DI ; MZ set zero condition code, clears carry + JMP SHORT DoContext ; MZ go do context + +High12: + SHR DI,1 + SHR DI,1 + SHR DI,1 + SHR DI,1 +Unpack12: + AND DI,0FFFH ; Clears carry +DoContext: + PUSH SS + POP DS + return + +HURTFAT: + MOV ES:[BP.dpb_free_cnt],-1 ; Err in FAT must force recomp of freespace + PUSH AX + MOV AH,allowed_fail + 80h + MOV Allowed,allowed_fail +; +; Signal Bad FAT to INT int_fatal_abort handler. We have an invalid cluster. +; + MOV DI,0FFFH ; In case INT int_fatal_abort returns (it shouldn't) + invoke FATAL + CMP AL,3 + CLC + JNZ OKU_RET ; Try to ignore bad FAT + STC ; User said FAIL +OKU_RET: + POP AX + return +EndProc UNPACK + +Break + +; Inputs: +; BX = Cluster number +; DX = Data +; ES:BP = Pointer to drive DPB +; Outputs: +; The data is stored in the FAT at the given cluster. +; SI,DX,DI all destroyed +; Carry set means error (currently user FAILed to I 24) +; No other registers affected + + procedure PACK,NEAR + DOSAssume CS,,"Pack" + ASSUME ES:NOTHING + + Assert ISDPB,,"Pack" + CALL MAPCLUSTER +ASSUME DS:NOTHING + JC DoContext + MOV SI,[DI] + JZ Aligned ; byte (not nibble) aligned + PUSH CX ; move data to upper 12 bits + MOV CL,4 + SHL DX,CL + POP CX + AND SI,0FH ; leave in original low 4 bits + JMP SHORT PACKIN +ALIGNED: + CMP ES:[BP.dpb_max_cluster],4096-10 ; MZ 16 bit fats? + JAE Pack16 ; MZ yes, go clobber original data + AND SI,0F000H ; MZ leave in upper 4 bits of original + AND DX,0FFFh ; MZ store only 12 bits + JMP SHORT PackIn ; MZ go store +Pack16: + XOR SI,SI ; MZ no original data +PACKIN: + OR SI,DX + MOV [DI],SI + LDS SI,[CURBUF] + TEST [SI.buf_flags],buf_dirty ;LB. if already dirty ;AN000; + JNZ yesdirty ;LB. don't increment dirty count ;AN000; + invoke INC_DIRTY_COUNT ;LB. ;AN000; + OR [SI.buf_flags],buf_dirty ;LB. ;AN000; +yesdirty: ;LB. ;AN000; + CMP BYTE PTR [CLUSSPLIT],0 + Context DS + retz ; Carry clear + PUSH AX + PUSH BX + PUSH CX + MOV AX,[CLUSSAVE] + MOV DS,WORD PTR [CURBUF+2] +ASSUME DS:NOTHING + ADD SI,BUFINSIZ + MOV [SI],AH + Context DS + PUSH AX + MOV DX,WORD PTR [CLUSSEC+2] ;F.C. >32mb ;AN000; + MOV WORD PTR [HIGH_SECTOR],DX ;F.C. >32mb ;AN000; + + MOV DX,WORD PTR [CLUSSEC] + MOV SI,1 + XOR AL,AL + invoke GETBUFFRB + POP AX + JC POPP_RET + LDS DI,[CURBUF] +ASSUME DS:NOTHING + TEST [DI.buf_flags],buf_dirty ;LB. if already dirty ;AN000; + JNZ yesdirty2 ;LB. don't increment dirty count ;AN000; + invoke INC_DIRTY_COUNT ;LB. ;AN000; + OR [DI.buf_flags],buf_dirty +yesdirty2: + ADD DI,BUFINSIZ + DEC DI + ADD DI,ES:[BP.dpb_sector_size] + MOV [DI],AL + CLC +POPP_RET: + PUSH SS + POP DS + POP CX + POP BX + POP AX + return + +EndProc PACK + +Break + +; Inputs: +; ES:BP Points to DPB +; BX Is cluster number +; Function: +; Get a pointer to the cluster +; Outputs: +; DS:DI Points to contents of FAT for given cluster +; DS:SI Points to start of buffer +; Zero Not set if cluster data is in high 12 bits of word +; Zero set if cluster data is in low 12 or 16 bits +; Carry set if failed. +; SI is destroyed. + + procedure MAPCLUSTER,NEAR + DOSAssume CS,,"MapCluster" + ASSUME ES:NOTHING + + Assert ISDPB,,"MapCluster" + MOV BYTE PTR [CLUSSPLIT],0 + SaveReg + MOV AX,BX ; AX = BX + MOV CX,4096-10 + CMP ES:[BP.dpb_max_cluster],CX ; MZ 16 bit fat? + JAE Map16 ; MZ yes, do 16 bit algorithm + SHR AX,1 ; AX = BX/2 +Map16: ; MZ skip prev => AX=2*BX + XOR DI,DI ; >32mb fat ;AN000; + ADD AX,BX ; AX = 1.5*fat = byte offset in fat + ADC DI,0 ; >32mb fat ;AN000; +DoConvert: + MOV CX,ES:[BP.dpb_sector_size] +IF FastDiv +; +; Gross hack: 99% of all disks have 512 bytes per sector. We test for this +; case and apply a really fast algorithm to get the desired results +; +; Divide method takes 158 (XOR and DIV) +; Fast method takes 20 +; +; This saves a bunch. +; + CMP CX,512 ; 4 Is this 512 byte sector? + JZ Nodiv ;F.C. >32mb ;AN000; + JMP DoDiv ; 4/16 No, go do divide +Nodiv: ;F.C. >32mb ;AN000; + MOV DX,AX ; 2 get set for remainder + AND DX,512-1 ; 4 Form remainder + MOV AL,AH ; 2 + SHR AL,1 ; 2 + CBW ; 2 Fast divide by 512 + OR DI,DI ;>32mb >64k ? ;AN000; + JZ g64k ;>32mb no ;AN000; + OR AX,80H ;>32mb ;AN000; +g64k: +ELSE + XOR DX,DX ; 3 + DIV CX ; 155 AX is FAT sector # DX is sector index +ENDIF +DivDone: + ADD AX,ES:[BP.dpb_first_FAT] + DEC CX ; CX is sector size - 1 + SaveReg + MOV DX,AX + MOV [HIGH_SECTOR],0 ;F.C. >32mb low sector # + XOR AL,AL + MOV SI,1 + invoke GETBUFFRB + RestoreReg ; CX is sec siz-1, AX is offset in sec + JC MAP_POP + LDS SI,[CURBUF] +ASSUME DS:NOTHING + LEA DI,[SI.BufInSiz] + ADD DI,AX + CMP AX,CX + JNZ MAPRET + MOV AL,[DI] + Context DS + INC BYTE PTR [CLUSSPLIT] + MOV BYTE PTR [CLUSSAVE],AL + MOV WORD PTR [CLUSSEC],DX + MOV WORD PTR [CLUSSEC+2],0 ;F.C. >32mb ;AN000; + INC DX + MOV [HIGH_SECTOR],0 ;F.C. >32mb FAT sector <32mb ;AN000; + XOR AL,AL + MOV SI,1 + invoke GETBUFFRB + JC MAP_POP + LDS SI,[CURBUF] +ASSUME DS:NOTHING + LEA DI,[SI.BufInSiz] + MOV AL,[DI] + Context DS + MOV BYTE PTR [CLUSSAVE+1],AL + MOV DI,OFFSET DOSGROUP:CLUSSAVE +MAPRET: + RestoreReg + XOR AX,AX ; MZ allow shift to clear carry + CMP ES:[BP.dpb_max_cluster],4096-10 ; MZ is this 16-bit fat? + JAE MapSet ; MZ no, set flags + MOV AX,BX +MapSet: + TEST AL,1 ; set zero flag if not on boundary + RestoreReg + return + +MAP_POP: + RestoreReg + return +IF FastDiv +DoDiv: + XOR DX,DX ; 3 + DIV CX ; 155 AX is FAT sector # DX is sector index + JMP DivDone ;15 total=35 +ENDIF + +EndProc MAPCLUSTER + +Break + +; Inputs: +; ES:DI points to an SFT for the drive of intrest (local only, +; giving a NET SFT will produce system crashing results). +; DS DOSGROUP +; Function: +; Can be used by an SFT routine (like CLOSE) to invalidate buffers +; if disk changed. +; In other respects, same as FATREAD_CDS. +; (note ES:DI destroyed!) +; Outputs: +; Carry set if error (currently user FAILed to I 24) +; NOTE: This routine may cause FATREAD_CDS to "miss" a disk change +; as far as invalidating curdir_ID is concerned. +; Since getting a true disk changed on this call is a screw up +; anyway, that's the way it goes. + + procedure FATREAD_SFT,NEAR + DOSAssume CS,,"FATRead_SFT" + ASSUME ES:NOTHING + + LES BP,ES:[DI.sf_devptr] + Assert ISDPB,,"FatReadSFT" + MOV AL,ES:[BP.dpb_drive] + MOV [THISDRV],AL + invoke GOTDPB ;Set THISDPB + CALL FAT_GOT_DPB + return +EndProc FATREAD_SFT + +; Inputs: +; DS:DOSGROUP +; ES:DI points to an CDS for the drive of intrest (local only, +; giving a NET or NUL CDS will produce system crashing results). +; Function: +; If disk may have been changed, media is determined and buffers are +; flagged invalid. If not, no action is taken. +; Outputs: +; ES:BP = Drive parameter block +; [THISDPB] = ES:BP +; [THISDRV] set +; Carry set if error (currently user FAILed to I 24) +; DS preserved , all other registers destroyed + + procedure FATREAD_CDS,NEAR + DOSAssume CS,,"FATRead_CDS" + ASSUME ES:NOTHING + + PUSH ES + PUSH DI + LES BP,ES:[DI.curdir_devptr] + Assert ISDPB,,"FatReadCDS" + MOV AL,ES:[BP.dpb_drive] + MOV [THISDRV],AL + invoke GOTDPB ;Set THISDPB + CALL FAT_GOT_DPB + POP DI ;Get back CDS pointer + POP ES + retc + JNZ NO_CHANGE ;Media NOT changed +; Media changed. We now need to find all CDS structures which use this +; DPB and invalidate their ID pointers. +MED_CHANGE: + XOR AX,AX + DEC AX ;AX = -1 + PUSH DS + MOV CL,[CDSCOUNT] + XOR CH,CH ; CX is number of structures + LDS SI,ES:[DI.curdir_devptr] ; Find all CDS with this devptr +ASSUME DS:NOTHING + LES DI,[CDSADDR] ; Start here +CHECK_CDS: + TEST ES:[DI.curdir_flags],curdir_isnet + JNZ NEXTCDS ; Leave NET guys alone!! + PUSH ES + PUSH DI + LES DI,ES:[DI.curdir_devptr] + invoke POINTCOMP + POP DI + POP ES + JNZ NEXTCDS ; CDS not for this drive + TEST ES:[DI.curdir_ID],AX + JZ NEXTCDS ; If root, leave root + MOV ES:[DI.curdir_ID],AX ; else invalid +NEXTCDS: + ADD DI,SIZE curdir_list ; Point to next CDS + LOOP CHECK_CDS + POP DS + DOSAssume CS,,"FAT/NextCDS" +NO_CHANGE: + LES BP,[THISDPB] + CLC + return +EndProc FATREAD_CDS + +Break + + procedure FAT_operation,NEAR +FATERR: + DOSAssume CS,,"FATERR" + MOV ES:[BP.dpb_free_cnt],-1 ; Err in FAT must force recomp of freespace + AND DI,STECODE ; Put error code in DI + MOV [ALLOWED],allowed_FAIL + allowed_RETRY + MOV AH,2 + allowed_FAIL + allowed_RETRY ; While trying to read FAT + MOV AL,BYTE PTR [THISDRV] ; Tell which drive + invoke FATAL1 + LES BP,[THISDPB] + CMP AL,3 + JNZ FAT_GOT_DPB ; User said retry + STC ; User said FAIL + return + +FAT_GOT_DPB: + Context DS + MOV AL,DMEDHL + MOV AH,ES:[BP.dpb_UNIT] + MOV WORD PTR [DEVCALL],AX + MOV BYTE PTR [DEVCALL.REQFUNC],DEVMDCH + MOV [DEVCALL.REQSTAT],0 + MOV AL,ES:[BP.dpb_media] + MOV BYTE PTR [CALLMED],AL + PUSH ES + PUSH DS + MOV BX,OFFSET DOSGROUP:DEVCALL + LDS SI,ES:[BP.dpb_driver_addr] ; DS:SI Points to device header +ASSUME DS:NOTHING + POP ES ; ES:BX Points to call header + invoke DEVIOCALL2 + Context DS + POP ES ; Restore ES:BP + MOV DI,[DEVCALL.REQSTAT] + TEST DI,STERR + JNZ FATERR + XOR AH,AH + XCHG AH,ES:[BP.dpb_first_access] ; Reset dpb_first_access + MOV AL,BYTE PTR [THISDRV] ; Use physical unit number +; See if we had changed volume id by creating one on the diskette + cmp [VOLCHNG_FLAG],AL + jnz CHECK_BYT + mov [VOLCHNG_FLAG],-1 + jmp GOGETBPB ; Need to get device driver to read in + ; new volume label. +CHECK_BYT: + OR AH,BYTE PTR [CALLRBYT] + JNS CHECK_ZR ; ns = 0 or 1 + JMP NEWDSK + +CHECK_ZR: + JZ CHKBUFFDIRT ; jump if I don't know + CLC + return ; If Media not changed (NZ) + +DISK_CHNG_ERR: +ASSUME DS:NOTHING + PUSH ES + PUSH BP + LES BP,ES:[BP.dpb_driver_addr] ; Get device pointer + TEST ES:[BP.SDEVATT],DEVOPCL ; Did it set vol id? + POP BP + POP ES + JZ FAIL_OPJ2 ; Nope, FAIL + PUSH DS ; Save buffer pointer for ignore + PUSH DI + Context DS + MOV [ALLOWED],allowed_FAIL + allowed_RETRY + PUSH ES + LES DI,[CALLVIDM] ; Get volume ID pointer + MOV WORD PTR [EXTERRPT+2],ES + POP ES + MOV WORD PTR [EXTERRPT],DI + MOV AX,error_I24_wrong_disk + MOV [READOP],1 ; Write + invoke HARDERR + POP DI ; Get back buffer for ignore + POP DS +ASSUME DS:NOTHING + CMP AL,3 +FAIL_OPJ2: + JZ FAIL_OP + JMP FAT_GOT_DPB ; Retry + +CHKBUFFDIRT: + DOSAssume CS,,"FAT/ChkBuffDirt" +; LDS DI,[BUFFHEAD] +ASSUME DS:NOTHING + XOR DX,DX ;LB. ;AN000; + LDS DI,[BUF_HASH_PTR] ;LB. scan from 1st entry ;AN000; + MOV CX,[BUF_HASH_COUNT] ;LB. get Hash entry count ;AN000; + +scan_dirty: + CMP [DI.Dirty_Count],0 ;LB. if not dirty ;AN000; + JZ GETNEXT ;LB. get next hash entry ;AN000; + PUSH DS ;LB. save hash entry addr ;AN000; + PUSH DI ;LB. ;AN000; + invoke Map_Entry ;LB. ;AN000; +NBUFFER: ; Look for dirty buffers + CMP AL,[DI.buf_ID] + JNZ LFNXT ; Not for this unit + TEST [DI.buf_flags],buf_dirty + JZ LFNXT + POP DI ;LB. restore regs ;AN000; + POP DS ;LB. ;AN000; + Context DS + CLC + return ; There is a dirty buffer, assume Media OK (NZ) + +FAIL_OP: + Context DS + STC + return + +ASSUME DS:NOTHING +LFNXT: + mov DI,[DI.buf_next] ;; 1/19/88 + CMP DI,[FIRST_BUFF_ADDR] ;; 1/19/88 + JNZ NBUFFER + POP DI ;LB. restore regs ;AN000; + POP DS ;LB. ;AN000; +GETNEXT: + ADD DI,size BUFFER_HASH_ENTRY ;LB. next entry ;AN000; + LOOP scan_dirty ;LB. scan next entry ;AN000; +; If no dirty buffers, assume Media changed +NEWDSK: + MOV ES:[BP.dpb_free_cnt],-1 ; Media changed, must re-compute + ; NOTE: It is TECHNICALLY more correct +ASSUME DS:NOTHING + XOR DX,DX ;LB. ;AN000; + MOV [HIGH_SECTOR],DX ;LB. scan from 1st entry ;AN000; + MOV CX,[BUF_HASH_COUNT] ;LB. get Hash entry count ;AN000; + +NxtHash: + invoke GETCURHEAD ;LB. get Hash entry buffer header ;AN000; + ; to do this AFTER the check for +ASSUME DS:NOTHING +NXBUFFER: + CMP AL,[DI.buf_ID] ; For this drive? + JZ OLDDRV2 ;LB. yes ;AN000; + mov DI,[DI.buf_next] ;LB. get next buffer 1/19/88 ;AN000; + JMP SHORT SKPBUFF ;LB. ;AN000; +OLDDRV2: + TEST [DI.buf_flags],buf_dirty + JZ OldDrv + JMP Disk_Chng_Err ; Disk changed but dirty buffers +OLDDRV: + MOV WORD PTR [DI.buf_ID],(buf_visit SHL 8) OR 0FFH ; Free up buffer + invoke SCANPLACE +SKPBUFF: + CMP DI,[FIRST_BUFF_ADDR] ;LB. end of chain 1/19/88 ;AN000; + JNZ NXBUFFER ;LB. no ;AN000; + INC DX ;LB. ;AN000; + LOOP NxtHash ;LB. ;AN000; + CMP [SC_CACHE_COUNT],0 ;LB. look ahead buffers ? ;AN001; + JZ GOGETBPB ;LB. no ;AN001; + CMP AL,[CURSC_DRIVE] ;LB. same as changed drive ;AN001; + JNZ GOGETBPB ;LB. no ;AN001; + MOV [CURSC_DRIVE],-1 ;LB. invalidate look ahead buffers ;AN000; +GOGETBPB: + LDS DI,ES:[BP.dpb_driver_addr] + TEST [DI.SDEVATT],ISFATBYDEV + JNZ GETFREEBUF + context DS + MOV BX,2 + CALL UNPACK ; Read the first FAT sector into CURBUF +FAIL_OPJ: + JC FAIL_OP + LDS DI,[CURBUF] +ASSUME DS:NOTHING + JMP SHORT GOTGETBUF + +GETFREEBUF: +ASSUME DS:NOTHING + PUSH ES ; Get a free buffer for BIOS to use + PUSH BP +; LDS DI,[BUFFHEAD] + XOR DX,DX ;LB. fake to get 1st ;AN000; + MOV [HIGH_SECTOR],DX ;LB. buffer addr ;AN000; + invoke GETCURHEAD ;LB. ;AN000; + + invoke BUFWRITE + POP BP + POP ES + JC FAIL_OPJ +GOTGETBUF: + ADD DI,BUFINSIZ + MOV WORD PTR [CALLXAD+2],DS + Context DS + MOV WORD PTR [CALLXAD],DI + MOV AL,DBPBHL + MOV AH,BYTE PTR ES:[BP.dpb_UNIT] + MOV WORD PTR [DEVCALL],AX + MOV BYTE PTR [DEVCALL.REQFUNC],DEVBPB + MOV [DEVCALL.REQSTAT],0 + MOV AL,BYTE PTR ES:[BP.dpb_media] + MOV [CALLMED],AL + PUSH ES + PUSH DS + PUSH WORD PTR ES:[BP.dpb_driver_addr+2] + PUSH WORD PTR ES:[BP.dpb_driver_addr] + MOV BX,OFFSET DOSGROUP:DEVCALL + POP SI + POP DS ; DS:SI Points to device header +ASSUME DS:NOTHING + POP ES ; ES:BX Points to call header + invoke DEVIOCALL2 + POP ES ; Restore ES:BP + Context DS + MOV DI,[DEVCALL.REQSTAT] + TEST DI,STERR + JNZ FATERRJ + MOV AL,BYTE PTR ES:[BP.dpb_media] + LDS SI,[CALLBPB] +ASSUME DS:NOTHING + MOV ES:[BP].DPB_next_free,0 ; recycle scanning pointer + invoke $SETDPB + LDS DI,[CALLXAD] ; Get back buffer pointer + MOV AL,BYTE PTR ES:[BP.dpb_FAT_count] + MOV [DI.buf_wrtcnt-BUFINSIZ],AL ;>32mb ;AN000; + MOV AX,ES:[BP.dpb_FAT_size] ;>32mb ;AC000; + MOV [DI.buf_wrtcntinc-BUFINSIZ],AX ;>32mb Correct buffer info ;AC000; + + Context DS + XOR AL,AL ;Media changed (Z), Carry clear + return + +FATERRJ: JMP FATERR + +EndProc FAT_operation + +CODE ENDS + END diff --git a/v4.0/src/DOS/FCB.ASM b/v4.0/src/DOS/FCB.ASM new file mode 100644 index 0000000..2b51da6 --- /dev/null +++ b/v4.0/src/DOS/FCB.ASM @@ -0,0 +1,504 @@ +; SCCSID = @(#)fcb.asm 1.2 85/07/23 +; SCCSID = @(#)fcb.asm 1.2 85/07/23 +TITLE FCB - FCB parse calls for MSDOS +NAME FCB +; Low level routines for parsing names into FCBs and analyzing +; filename characters +; +; MakeFcb +; NameTrans +; PATHCHRCMP +; GetLet +; TESTKANJ +; NORMSCAN +; DELIM +; +; Revision history: +; +; A000 version 4.00 Jan. 1988 +; + +; +; get the appropriate segment definitions +; +.xlist +include dosseg.asm + + +TableLook equ -1 + +Table Segment +Zero label byte +Table ENDS + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +include dossym.inc +include devsym.inc +include doscntry.inc ;AN000; 2/12/KK +.cref +.list + + i_need Name1,BYTE + i_need Creating,BYTE + i_need Attrib,BYTE + i_need SpaceFlag,BYTE + i_need FILE_UCASE_TAB,byte ;DOS 3.3 + i_need COUNTRY_CDPG,byte ;AN000; 2/12/KK + i_need DrvErr,BYTE ;AN000; 2/12/KK + i_need DOS34_FLAG,WORD ;AN000; 2/12/KK + + procedure MakeFcb,NEAR +ScanSeparator = 1 +DRVBIT EQU 2 +NAMBIT EQU 4 +EXTBIT EQU 8 + MOV BYTE PTR [SpaceFlag],0 + XOR DL,DL ; Flag--not ambiguous file name + TEST AL,DRVBIT ; Use current drive field if default? + JNZ DEFDRV + MOV BYTE PTR ES:[DI],0 ; No - use default drive +DEFDRV: + INC DI + MOV CX,8 + TEST AL,NAMBIT ; Use current name fields as defualt? + XCHG AX,BX ; Save bits in BX + MOV AL," " + JZ FILLB ; If not, go fill with blanks + ADD DI,CX + XOR CX,CX ; Don't fill any +FILLB: + REP STOSB + MOV CL,3 + TEST BL,EXTBIT ; Use current extension as default + JZ FILLB2 + ADD DI,CX + XOR CX,CX +FILLB2: + REP STOSB + XCHG AX,CX ; Put zero in AX + STOSW + STOSW ; Initialize two words after to zero + SUB DI,16 ; Point back at start + TEST BL,ScanSeparator; Scan off separators if not zero + JZ SKPSPC + CALL SCANB ; Peel off blanks and tabs + CALL DELIM ; Is it a one-time-only delimiter? + JNZ NOSCAN + INC SI ; Skip over the delimiter +SKPSPC: + CALL SCANB ; Always kill preceding blanks and tabs +NOSCAN: + CALL GETLET + JBE NODRV ; Quit if termination character + IF DBCS ;AN000; + CALL TESTKANJ ;AN000;; 2/18/KK + JNE NODRV ;AN000;; 2/18/KK + ENDIF ;AN000; + CMP BYTE PTR[SI],":" ; Check for potential drive specifier + JNZ NODRV + INC SI ; Skip over colon + SUB AL,"@" ; Convert drive letter to drive number (A=1) + JBE BADDRV ; Drive letter out of range + + PUSH AX + Invoke GetVisDrv + POP AX + JNC HavDrv + CMP [DrvErr],error_not_DOS_disk ; if not FAt drive ;AN000; + JZ HavDrv ; assume ok ;AN000; +BADDRV: + MOV DL,-1 +HAVDRV: + STOSB ; Put drive specifier in first byte + INC SI + DEC DI ; Counteract next two instructions +NODRV: + DEC SI ; Back up + INC DI ; Skip drive byte + + entry NORMSCAN + + MOV CX,8 + CALL GETWORD ; Get 8-letter file name + CMP BYTE PTR [SI],"." + JNZ NODOT + INC SI ; Skip over dot if present + TEST [DOS34_FLAG],DBCS_VOLID2 ;AN000; + JZ VOLOK ;AN000; + MOVSB ; 2nd byte of DBCS ;AN000; + MOV CX,2 ;AN000; + JMP SHORT contvol ;AN000; +VOLOK: + MOV CX,3 ; Get 3-letter extension +contvol: + CALL MUSTGETWORD +NODOT: + MOV AL,DL + return + +NONAM: + ADD DI,CX + DEC SI + return + +GETWORD: + CALL GETLET + JBE NONAM ; Exit if invalid character + DEC SI +; +; UGH!!! Horrible bug here that should be fixed at some point: +; If the name we are scanning is longer than CX, we keep on reading! +; +MUSTGETWORD: + CALL GETLET +; +; If spaceFlag is set then we allow spaces in a pathname +; + JB FILLNAM + JNZ MustCheckCX + TEST BYTE PTR [SpaceFlag],0FFh + JZ FILLNAM + CMP AL," " + JNZ FILLNAM + +MustCheckCX: + JCXZ MUSTGETWORD + DEC CX + CMP AL,"*" ; Check for ambiguous file specifier + JNZ NOSTAR + MOV AL,"?" + REP STOSB +NOSTAR: + STOSB + + IF DBCS ;AN000; + CALL TESTKANJ ;AN000; + JZ NOTDUAL3 ;AN000; + JCXZ BNDERR ; Attempt to straddle boundry ;AN000; + MOVSB ; Transfer second byte ;AN000; + DEC CX ;AN000; + JMP MUSTGETWORD ;AN000; +BNDERR: ;AN000; + TEST [DOS34_FLAG],DBCS_VOLID ;AN000; + JZ notvolumeid ;AN000; + TEST [DOS34_FLAG],DBCS_VOLID2 ;AN000; + JNZ notvolumeid ;AN000; + OR [DOS34_FLAG],DBCS_VOLID2 ;AN000; + JMP MUSTGETWORD ;AN000; + +notvolumeid: +;; INC CX ; Undo the store of the first byte + DEC DI + MOV AL," " ;PTM. ;AN000; + STOSB ;PTM. ;AN000; + INC SI ;PTM. ;AN000; + JMP MUSTGETWORD ;PTM. ;AN000; + +NOTDUAL3: ;AN000; + ENDIF ;AN000; + + CMP AL,"?" + JNZ MUSTGETWORD + OR DL,1 ; Flag ambiguous file name + JMP MUSTGETWORD +FILLNAM: + MOV AL," " + REP STOSB + DEC SI + return + +SCANB: + LODSB + CALL SPCHK + JZ SCANB + IF DBCS ;AN000; ;AN000; + CMP AL,81H ;AN000;; 1ST BYTE OF DBCS BLANK 2/18/KK ;AN000; + JNE SCANB_EXIT ;AN000;; 2/18/KK 3/31/KK revoved ;AN000; + CALL TESTKANJ ;AN000;; 2/23/KK 3/31/KK revoved ;AN000; + JE SCANB_EXIT ;AN000;; 2/18/KK 3/31/KK revoved ;AN000; + CMP BYTE PTR [SI],40H;AN000;H ; 2ND BYTE OF DBCS BLANK 2/18/KK 3/31/KK revove;AN000; + JNE SCANB_EXIT ;AN000;; 2/18/KK 3/31/KK revoved ;AN000; + INC SI ;AN000;; 2/18/KK 3/31/KK revoved ;AN000; + JMP SCANB ;AN000;; 2/18/KK 3/31/KK revoved ;AN000; + SCANB_EXIT: ;AN000;; 2/18/KK 3/31/KK revoved ;AN000; + ENDIF ;AN000; + DEC SI + return +EndProc MakeFCB + +; +; NameTrans is used by FindPath to scan off an element of a path. We must +; allow spaces in pathnames +; +; Inputs: DS:SI points to start of path element +; Outputs: Name1 has unpacked name, uppercased +; ES = DOSGroup +; DS:SI advanced after name +; Registers modified: DI,AX,DX,CX +procedure NameTrans,near + ASSUME DS:NOTHING,ES:NOTHING + MOV BYTE PTR [SpaceFlag],1 + context ES + MOV DI,OFFSET DOSGROUP:NAME1 + PUSH DI + MOV AX,' ' + MOV CX,5 + STOSB + REP STOSW ; Fill "FCB" at NAME1 with spaces + XOR AL,AL ; Set stuff for NORMSCAN + MOV DL,AL + STOSB + POP DI + + CALL NORMSCAN +IF DBCS ;AN000;;KK. + MOV AL,[NAME1] ;AN000;;KK. check 1st char + invoke testkanj ;AN000;;KK. dbcs ? + JZ notdbcs ;AN000;;KK. no + return ;AN000;;KK. yes +notdbcs: ;AN000; +ENDIF ;AN000; + CMP [NAME1],0E5H + retnz + MOV [NAME1],5 ; Magic name translation + return + +EndProc nametrans + +Break + +If TableLook +ChType Macro ch,bits + ORG CharType-Zero+ch + db bits + ENDM + +Table SEGMENT + PUBLIC CharType +Public FCB001S,FCB001E +FCB001S label byte +CharType DB 256 dup (-1) + ChType ".", + ChType '"', + ChType "/", + ChType "\", + ChType "[", + ChType "]", + ChType ":", + ChType "<", + ChType "|", + ChType ">", + ChType "+", + ChType "=", + ChType ";", + ChType ",", + ChType 0, ; NUL + ChType 1, ; ^A + ChType 2, ; ^b + ChType 3, ; ^c + ChType 4, ; ^d + ChType 5, ; ^e + ChType 6, ; ^f + ChType 7, ; ^g + ChType 8, ; ^h + ChType 9, ; Tab + ChType 10, ; ^j + ChType 11, ; ^k + ChType 12, ; ^l + ChType 13, ; ^m + ChType 14, ; ^n + ChType 15, ; ^o + ChType 16, ; ^p + ChType 17, ; ^q + ChType 18, ; ^r + ChType 19, ; ^s + ChType 20, ; ^t + ChType 21, ; ^u + ChType 22, ; ^v + ChType 23, ; ^w + ChType 24, ; ^x + ChType 25, ; ^y + ChType 26, ; ^z + ChType 27, ; ^[ + ChType 28, ; ^\ + ChType 29, ; ^] + ChType 30, ; ^^ + ChType 31, ; ^_ + ChType " ", + ChType 255, -1 +FCB001E label byte +Table ENDS +ENDIF +; +; Get a byte from [SI], convert it to upper case, and compare for delimiter. +; ZF set if a delimiter, CY set if a control character (other than TAB). +; +; DOS 3.3 modification for file char upper case. F.C. 5/29/86 + procedure GetLet,NEAR + LODSB + entry GetLet2 ;AN000;; called by uCase + PUSH BX + MOV BX,OFFSET DOSGROUP:FILE_UCASE_TAB+2 + getget: + CMP AL,"a" + JB CHK1 + CMP AL,"z" + JA CHK1 + SUB AL,20H ; Convert to upper case +CHK1: + CMP AL,80H ; DOS 3.3 + JB GOTIT ; DOS 3.3 + SUB AL,80H ;translate to upper case with this index +; + XLAT BYTE PTR CS:[BX] +If TableLook +GOTIT: + PUSH AX + MOV BX,OFFSET DOSGROUP:CharType + XLAT BYTE PTR CS:[BX] + + TEST AL,fChk + POP AX + POP BX + RET + entry GetLet3 ;AN000; called by uCase + PUSH BX ;AN000; + JMP getget ;AN000; + +ELSE +GOTIT: + POP BX + CMP AL,"." + retz + CMP AL,'"' + retz + CALL PATHCHRCMP + retz + CMP AL,"[" + retz + CMP AL,"]" + retz +ENDIF + +entry DELIM + +IF TableLook + PUSH AX + PUSH BX + MOV BX,OFFSET DOSGroup:CharType + XLAT BYTE PTR CS:[BX] + TEST AL,fDelim + POP BX + POP AX + RET +ELSE + CMP AL,":" + retz + + CMP AL,"<" + retz + CMP AL,"|" + retz + CMP AL,">" + retz + + CMP AL,"+" + retz + CMP AL,"=" + retz + CMP AL,";" + retz + CMP AL,"," + retz +ENDIF +entry SPCHK +IF TableLook + PUSH AX + PUSH BX + MOV BX,OFFSET DOSGroup:CharType + XLAT BYTE PTR CS:[BX] + TEST AL,fSpChk + POP BX + POP AX + RET +ELSE + CMP AL,9 ; Filter out tabs too + retz +; WARNING! " " MUST be the last compare + CMP AL," " + return +ENDIF +EndProc GetLet + +Procedure PATHCHRCMP,NEAR + CMP AL,'/' + JBE PathRet + CMP AL,'\' + return +GotFor: + MOV AL,'\' + return +PathRet: + JZ GotFor + return +EndProc PathChrCMP + + + IF DBCS +;--------------------- 2/12/KK +; Function: Check if an input byte is in the ranges of DBCS vectors. +; +; Input: AL ; Code to be examined +; +; Output: ZF = 1 : AL is SBCS ZF = 0 : AL is a DBCS leading byte +; +; Register: All registers are unchanged except FL +; +procedure TESTKANJ,NEAR ;AN000; + call Chk_DBCS ;AN000; + jc TK_DBCS ;AN000; + cmp AL,AL ; set ZF ;AN000; + return ;AN000; +TK_DBCS: + PUSH AX ;AN000; + XOR AX,AX ;Set ZF ;AN000; + INC AX ;Reset ZF ;AN000; + POP AX ;AN000; + return ;AN000; +EndProc TESTKANJ ;AN000; +; +Chk_DBCS PROC ;AN000; + PUSH DS ;AN000; + PUSH SI ;AN000; + PUSH BX ;AN000; + Context DS ;AN000; + MOV BX,offset DOSGROUP:COUNTRY_CDPG.ccSetDBCS ;AN000; + LDS SI,[BX+1] ; set EV address to DS:SI ;AN000; + ADD SI,2 ; Skip length ;AN000; +DBCS_LOOP: + CMP WORD PTR [SI],0 ; terminator ? ;AN000; + JE NON_DBCS ; if yes, no DBCS ;AN000; + CMP AL,[SI] ; else ;AN000; + JB DBCS01 ; check if AL is ;AN000; + CMP AL,[SI+1] ; in a range of Ev ;AN000; + JA DBCS01 ; if yes, DBCS ;AN000; + STC ; else ;AN000; + JMP DBCS_EXIT ; try next DBCS Ev ;AN000; +DBCS01: + ADD SI,2 ;AN000; + JMP DBCS_LOOP ;AN000; +NON_DBCS: + CLC ;AN000; +DBCS_EXIT: + POP BX ;AN000; + POP SI ;AN000; + POP DS ;AN000; + RET ;AN000; +Chk_DBCS ENDP ;AN000; + ENDIF ;AN000; +CODE ENDS + END + ;AN000; diff --git a/v4.0/src/DOS/FCBIO.ASM b/v4.0/src/DOS/FCBIO.ASM new file mode 100644 index 0000000..8b27d72 --- /dev/null +++ b/v4.0/src/DOS/FCBIO.ASM @@ -0,0 +1,1185 @@ +; SCCSID = @(#)fcbio.asm 1.5 85/07/30 +; SCCSID = @(#)fcbio.asm 1.5 85/07/30 +TITLE FCBIO - FCB system calls +NAME FCBIO + +; +; Ancient 1.0 1.1 FCB system calls +; regen save +; $GET_FCB_POSITION written none none +; $FCB_DELETE written none none +; $GET_FCB_FILE_LENGTH written none none +; $FCB_CLOSE written close none +; $FCB_RENAME written none none +; SaveFCBInfo +; ResetLRU +; SetOpenAge +; LRUFCB +; FCBRegen +; BlastSFT +; CheckFCB +; SFTFromFCB +; FCBHardErr +; +; Revision history: +; +; Created: ARR 4 April 1983 +; MZ 6 June 1983 completion of functions +; MZ 15 Dec 1983 Brain damaged programs close FCBs multiple +; times. Change so successive closes work by +; always returning OK. Also, detect I/O to +; already closed FCB and return EOF. +; MZ 16 Jan 1984 More braindamage. Need to separate info +; out of sft into FCB for reconnection +; +; A000 version 4.00 Jan. 1988 +; +.xlist +; +; get the appropriate segment definitions +; +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +INCLUDE FASTOPEN.INC +.cref +.list + + AsmVars + + I_need OpenBuf,128 ; buffer for translating paths + I_need RenBuf,128 ; buffer for rename paths + i_need THISDPB,DWORD + i_need EXTERR,WORD + i_need ALLOWED,BYTE + I_need ThisSFT,DWORD ; SFT in use + I_need WFP_start,WORD ; pointer to canonical name + I_need Ren_WFP,WORD ; pointer to canonical name + I_need Attrib,BYTE ; Attribute for match attributes + I_need sftFCB,DWORD ; pointer to SFTs for FCB cache + I_need FCBLRU,WORD ; least recently used count + I_need Proc_ID,WORD ; current process ID + I_Need Name1,14 ; place for device names + I_need DEVPT,DWORD ; device pointer + I_need OpenLRU,WORD ; open age + I_need KeepCount,WORD ; number of fcbs to keep + I_need User_In_AX,WORD ; user input system call. + I_need JShare,DWORD ; share jump table + I_need FastOpenTable,BYTE ; DOS 3.3 fastopen +if debug + I_need BugLev,WORD + I_need BugTyp,WORD + include bugtyp.asm +endif + + +Break <$Get_FCB_Position - set random record fields to current pos> + +; +; $Get_FCB_Position - look at an FCB, retrieve the current position from the +; extent and next record field and set the random record field to point +; to that record +; +; Inputs: DS:DX point to a possible extended FCB +; Outputs: The random record field of the FCB is set to the current record +; Registers modified: all + +Procedure $Get_FCB_Position,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup + invoke GetExtended ; point to FCB + invoke GetExtent ; DX:AX is current record + MOV WORD PTR [SI.fcb_RR],AX ; drop in low order piece + MOV [SI+fcb_RR+2],DL ; drop in high order piece + CMP [SI.fcb_RECSIZ],64 + JAE GetFCBBye + MOV [SI+fcb_RR+2+1],DH ; Set 4th byte only if record size < 64 +GetFCBBye: + transfer FCB_Ret_OK +EndProc $GET_FCB_POSITION + +Break <$FCB_Delete - remove several files that match the input FCB> + +; +; $FCB_delete - given an FCB, remove all directory entries in the current +; directory that have names that match the FCB's ? marks. +; +; Inputs: DS:DX - point to an FCB +; Outputs: directory entries matching the FCB are deleted +; AL = FF if no entries were deleted. +; Registers modified: all + +Procedure $FCB_Delete,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup + MOV DI,OFFSET DOSGroup:OpenBuf ; appropriate place + invoke TransFCB ; convert FCB to path + JC BadPath ; signal no deletions + Context DS + invoke DOS_Delete ; wham + JC BadPath +GoodPath: + transfer FCB_Ret_OK ; do a good return +BadPath: +; + +; Error code is in AX +; + transfer FCB_Ret_Err ; let someone else signal the error +EndProc $FCB_DELETE + +Break <$Get_FCB_File_Length - return the length of a file> + +; +; $Get_FCB_File_Length - set the random record field to the length of the +; file in records (rounded up if partial). +; +; Inputs: DS:DX - point to a possible extended FCB +; Outputs: Random record field updated to reflect the number of records +; Registers modified: all + +Procedure $Get_FCB_File_Length,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup + invoke GetExtended ; get real FCB pointer + ; DX points to Input FCB + MOV DI,OFFSET DOSGroup:OpenBuf ; appropriate buffer + SaveReg ; save pointer to true FCB + Invoke TransFCB ; Trans name DS:DX, sets SATTRIB + RestoreReg + JC BadPath + SaveReg ; save pointer + Context DS + invoke Get_File_Info ; grab the info + RestoreReg ; get pointer back + JC BadPath ; invalid something + MOV DX,BX ; get high order size + MOV AX,DI ; get low order size + MOV BX,[SI.fcb_RECSIZ] ; get his record size + OR BX,BX ; empty record => 0 size for file + JNZ GetSize ; not empty + MOV BX,128 +GetSize: + MOV DI,AX ; save low order word + MOV AX,DX ; move high order for divide + XOR DX,DX ; clear out high + DIV BX ; wham + PUSH AX ; save dividend + MOV AX,DI ; get low order piece + DIV BX ; wham + MOV CX,DX ; save remainder + POP DX ; get high order dividend + JCXZ LengthStore ; no roundup + ADD AX,1 + ADC DX,0 ; 32-bit increment +LengthStore: + MOV WORD PTR [SI.FCB_RR],AX ; store low order + MOV [SI.FCB_RR+2],DL ; store high order + OR DH,DH + JZ GoodPath ; not storing insignificant zero + MOV [SI.FCB_RR+3],DH ; save that high piece +GoodRet: + transfer FCB_Ret_OK +EndProc $GET_FCB_FILE_LENGTH + +Break <$FCB_Close - close a file> + +; +; $FCB_Close - given an FCB, look up the SFN and close it. Do not free it +; as the FCB may be used for further I/O +; +; Inputs: DS:DX point to FCB +; Outputs: AL = FF if file was not found on disk +; Registers modified: all + +Procedure $FCB_Close,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup + XOR AL,AL ; default search attributes + invoke GetExtended ; DS:SI point to real FCB + JZ NoAttr ; not extended + MOV AL,[SI-1] ; get attributes +NoAttr: + MOV [Attrib],AL ; stash away found attributes + invoke SFTFromFCB + JC GoodRet ; MZ 16 Jan Assume death +; +; If the sharer is present, then the SFT is not regenable. Thus, there is +; no need to set the SFT's attribute. +; +;;; 9/8/86 F.C. save SFT attribute and restore it back when close is done + MOV AL,ES:[DI].sf_attr + XOR AH,AH + PUSH AX +;;; 9/8/86 F.C. save SFT attribute and restore it back when close is done + invoke CheckShare + JNZ NoStash + MOV AL,Attrib + MOV ES:[DI].sf_attr,AL ; attempted attribute for close +NoStash: + MOV AX,[SI].FCB_FDATE ; move in the time and date + MOV ES:[DI].sf_date,AX + MOV AX,[SI].FCB_FTIME + MOV ES:[DI].sf_time,AX + MOV AX,[SI].FCB_FilSiz + MOV WORD PTR ES:[DI].sf_size,AX + MOV AX,[SI].FCB_FilSiz+2 + MOV WORD PTR ES:[DI].sf_size+2,AX + OR ES:[DI].sf_Flags,sf_close_nodate + Context DS ; let Close see variables + invoke DOS_Close ; wham + LES DI,ThisSFT +;;; 9/8/86 F.C. restore SFT attribute + POP CX + MOV ES:[DI].sf_attr,CL +;;; 9/8/86 F.C. restore SFT attribute + PUSHF + TEST ES:[DI.sf_ref_count],-1 ; zero ref count gets blasted + JNZ CloseOK + PUSH AX + MOV AL,'M' + invoke BlastSFT + POP AX +CloseOK: + POPF + JNC GoodRet + CMP AL,error_invalid_handle + JZ GoodRet + MOV AL,error_file_not_found + transfer FCB_Ret_Err +EndProc $FCB_CLOSE + +Break <$FCB_Rename - change names in place> + +; +; $FCB_Rename - rename a file in place within a directory. Renames multiple +; files copying from the meta characters. +; +; Inputs: DS:DX point to an FCB. The normal name field is the source +; name of the files to be renamed. Starting at offset 11h +; in the FCB is the destination name. +; Outputs: AL = 0 -> no error occurred and all files were renamed +; AL = FF -> some files may have been renamed but: +; rename to existing file or source file not found +; Registers modified: all + +Procedure $FCB_Rename,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup + invoke GetExtended ; get pointer to real FCB + SaveReg + MOV AL,[SI] ; get drive byte + ADD SI,10h ; point to destination + MOV DI,OFFSET DOSGroup:RenBuf ; point to destination buffer + SaveReg <,DS,SI> ; save source pointer for TransFCB + MOV DS:[SI],AL ; drop in real drive + MOV DX,SI ; let TransFCB know where the FCB is + invoke TransFCB ; munch this pathname + RestoreReg > ; get path back + RestoreReg ; Original FCB pointer + JC BadRen ; bad path -> error + MOV SI,WFP_Start ; get pointer + MOV Ren_WFP,SI ; stash it + MOV DI,OFFSET DOSGroup:OpenBuf ; appropriate spot + invoke TransFCB ; wham + ; NOTE that this call is pointing + ; back to the ORIGINAL FCB so + ; SATTRIB gets set correctly + JC BadRen ; error + invoke DOS_Rename + JC BadRen + transfer FCB_Ret_OK +BadRen: +; +; AL has error code +; + transfer FCB_Ret_Err + +EndProc $FCB_RENAME + +Break + +; +; FCBs suffer from several problems. First, they are maintained in the +; user's space so he may move them at will. Second, they have a small +; reserved area that may be used for system information. Third, there was +; never any "rules for behavior" for FCBs; there was no protocol for their +; usage. +; +; This results in the following misbehavior: +; +; infinite opens of the same file: +; +; While (TRUE) { While (TRUE) { +; FCBOpen (FCB); FCBOpen (FCB); +; Read (FCB); Write (FCB); +; } } +; +; infinite opens of different files: +; +; While (TRUE) { While (TRUE) { +; FCBOpen (FCB[i++]); FCBOpen (FCB[i++]); +; Read (FCB); Write (FCB); +; } } +; +; multiple closes of the same file: +; +; FCBOpen (FCB); +; while (TRUE) +; FCBClose (FCB); +; +; I/O after closing file: +; +; FCBOpen (FCB); +; while (TRUE) { +; FCBWrite (FCB); +; FCBClose (FCB); +; } +; +; The following is am implementation of a methodology for emulating the +; above with the exception of I/O after close. We are NOT attempting to +; resolve that particular misbehavior. We will enforce correct behaviour in +; FCBs when they refer to a network file or when there is file sharing on +; the local machine. +; +; The reserved fields of the FCB (10 bytes worth) is divided up into various +; structures depending on the file itself and the state of operations of the +; OS. The information contained in this reserved field is enough to +; regenerate the SFT for the local non-shared file. It is assumed that this +; regeneration procedure may be expensive. The SFT for the FCB is +; maintained in a LRU cache as the ONLY performance inprovement. +; +; No regeneration of SFTs is attempted for network FCBs. +; +; To regenerate the SFT for a local FCB, it is necessary to determine if the +; file sharer is working. If the file sharer is present then the SFT is not +; regenerated. +; +; Finally, if there is no local sharing, the full name of the file is no +; longer available. We can make up for this by using the following +; information: +; +; The Drive number (from the DPB). +; The physical sector of the directory that contains the entry. +; The relative position of the entry in the sector. +; The first cluster field. +; The last used SFT. +; OR In the case of a device FCB +; The low 6 bits of sf_flags (indicating device type) +; The pointer to the device header +; +; +; We read in the particular directory sector and examine the indicated +; directory entry. If it matches, then we are kosher; otherwise, we fail. +; +; Some key items need to be remembered: +; +; Even though we are caching SFTs, they may contain useful sharing +; information. We enforce good behavior on the FCBs. +; +; Network support must not treat FCBs as impacting the ref counts on +; open VCs. The VCs may be closed only at process termination. +; +; If this is not an installed version of the DOS, file sharing will +; always be present. +; +; We MUST always initialize lstclus to = firclus when regenerating a +; file. Otherwise we start allocating clusters up the wazoo. +; +; Always initialize, during regeneration, the mode field to both isFCB +; and open_for_both. This is so the FCB code in the sharer can find the +; proper OI record. +; +; The test bits are: +; +; 00 -> local file +; 40 -> sharing local +; 80 -> network +; C0 -> local device + +Break + +; +; SaveFCBInfo - given an FCB and its associated SFT, copy the relevant +; pieces of information into the FCB to allow for subsequent +; regeneration. Poke LRU also. +; +; Inputs: ThisSFT points to a complete SFT. +; DS:SI point to the FCB (not an extended one) +; Outputs: The relevant reserved fields in the FCB are filled in. +; DS:SI preserved +; ES:DI point to sft +; Registers modified: All +; + +Procedure SaveFCBInfo,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup + LES DI,ThisSFT + Assert ISSFT,,"SaveFCBInfo" + invoke IsSFTNet + JZ SaveLocal ; if not network then save local info +; +;----- In net support ----- +; + MOV AX,WORD PTR ES:[DI].sf_serial_ID ;AN000;;IFS. save IFS ID + MOV WORD PTR [SI].FCB_netID,ax ;AN000;;IFS. +; SaveReg +; LES DI,DWORD PTR ES:[DI].sf_netid +; MOV WORD PTR [SI].FCB_netID,DI ; save net ID +; MOV WORD PTR [SI].FCB_netID+2,ES +; RestoreReg + MOV BL,FCBNETWORK +; +;----- END In net support ----- +; +IF debug + JMP SaveSFN +ELSE + JMP SHORT SaveSFN +ENDIF +SaveLocal: + IF Installed + Invoke CheckShare + JZ SaveNoShare ; no sharer + JMP SaveShare ; sharer present + +SaveNoShare: + TEST ES:[DI].sf_flags,devid_device + JNZ SaveNoShareDev ; Device +; +; Save no sharing local file information +; + MOV AX,WORD PTR ES:[DI].sf_dirsec ; get directory sector F.C. + MOV [SI].fcb_nsl_dirsec,AX + MOV AL,ES:[DI].sf_dirpos ; location in sector + MOV [SI].fcb_nsl_dirpos,AL + MOV AX,ES:[DI].sf_firclus ; first cluster + MOV [SI].fcb_nsl_firclus,AX + MOV BL,00 +; +; Create the bits field from the dirty/device bits of the flags word and the +; mode byte +; +SetFCBBits: + MOV AX,ES:[DI].sf_flags + AND AL,0C0h ; mask off drive bits + OR AL,BYTE PTR ES:[DI].sf_mode ; stick in open mode + MOV [SI].fcb_nsl_bits,AL ; save dirty info + JMP SaveSFN ; go and save SFN + +; +; Save no sharing local device information +; +SaveNoShareDev: + MOV AX,WORD PTR ES:[DI].sf_devptr + MOV WORD PTR [SI].FCB_nsld_drvptr,AX + MOV AX,WORD PTR ES:[DI].sf_devptr + 2 + MOV WORD PTR [SI].FCB_nsld_drvptr + 2,AX + MOV BL,FCBDEVICE + JMP SetFCBBits ; go and save SFN + +SaveShare: + ENDIF +; +;----- In share support ----- +; +if installed + Call JShare + 10 * 4 +else + Call ShSave +endif +; +;----- end in share support ----- +; +SaveSFN: + MOV AX,ES:[DI].sf_flags + AND AL,3Fh ; get real drive + OR AL,BL + MOV [SI].fcb_l_drive,AL + LEA AX,[DI-SFTable] +; +; Adjust for offset to table. +; + SUB AX,WORD PTR SftFCB + MOV BL,SIZE sf_entry + DIV BL + MOV [SI].FCB_sfn,AL ; last used SFN + MOV AX,FCBLRU ; get lru count + INC AX + MOV WORD PTR ES:[DI].sf_LRU,AX + JNZ SimpleStuff +; +; lru flag overflowed. Run through all FCB sfts and adjust: LRU < 8000h +; get set to 0. Others -= 8000h. This LRU = 8000h +; + MOV BX,sf_position + invoke ResetLRU +; +; Set new LRU to AX +; +SimpleStuff: + MOV FCBLRU,AX + return +EndProc SaveFCBInfo + +Break + +; +; ResetLRU - during lru updates, we may wrap at 64K. We must walk the +; entire set of SFTs and subtract 8000h from their lru counts and truncate +; at 0. +; +; Inputs: BX is offset into SFT field where lru firld is kept +; ES:DI point to SFT currently being updated +; Outputs: All FCB SFTs have their lru fields truncated +; AX has 8000h +; Registers modified: none + +Procedure ResetLRU,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING + Assert ISSFT,,"ResetLRU" + MOV AX,8000h + SaveReg + LES DI,sftFCB ; get pointer to head + MOV CX,ES:[DI].sfCount + LEA DI,[DI].sfTable ; point at table +ovScan: + SUB WORD PTR ES:[DI+BX],AX ; decrement lru count + JA ovLoop + MOV WORD PTR ES:[DI.BX],AX ; truncate at 0 +ovLoop: + ADD DI,SIZE SF_Entry ; advance to next + LOOP ovScan + RestoreReg + MOV ES:[DI+BX],AX + return +EndProc ResetLRU + +Break + +; +; SetOpenAge - In order to maintain the first N open files in the FCB cache, +; we keep the 'open age' or an LRU count based on opens. We update the +; count here and fill in the appropriate field. +; +; Inputs: ES:DI point to SFT +; Outputs: ES:DI has the open age field filled in. +; If open age has wraparound, we will have subtracted 8000h +; from all open ages. +; Registers modified: AX +; + +Procedure SetOpenAge,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING + Assert ISSFT,,"SetOpenAge" + MOV AX,OpenLRU + INC AX + MOV ES:[DI].sf_OpenAge,AX + JNZ SetDone + MOV BX,sf_Position+2 + invoke ResetLRU +SetDone: + MOV OpenLRU,AX + return +EndProc SetOpenAge + +Break + +; +; LRUFCB - find LRU fcb in cache. Set ThisSFT and return it. We preserve +; the first keepcount sfts if they are network sfts or if sharing is +; loaded. If carry is set then NO BLASTING is NECESSARY. +; +; Inputs: none +; Outputs: ES:DI point to SFT +; ThisSFT points to SFT +; SFT is zeroed +; Carry set of closes failed +; Registers modified: none +; + +Procedure LRUFCB,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING + Invoke Save_World +; +; Find nth oldest NET/SHARE FCB. We want to find its age for the second scan +; to find the lease recently used one that is younger than the open age. We +; operate be scanning the list n times finding the least age that is greater +; or equal to the previous minimum age. +; +; BP is the count of times we need to go through this loop. +; AX is the current acceptable minimum age to consider +; + mov bp,KeepCount ; k = keepcount; + XOR AX,AX ; low = 0; +; +; If we've scanned the table n times, then we are done. +; +lru1: + CMP bp,0 ; while (k--) { + JZ lru75 + DEC bp +; +; Set up for scan. +; +; AX is the minimum age for consideration +; BX is the minimum age found during the scan +; SI is the position of the entry that corresponds to BX +; + MOV BX,-1 ; min = 0xffff; + MOV si,BX ; pos = 0xffff; + LES DI,SFTFCB ; for (CX=FCBCount; CX>0; CX--) + MOV CX,ES:[DI].sfCount + LEA DI,[DI].sfTable +; +; Innermost loop. If the current entry is free, then we are done. Or, if the +; current entry is busy (indicating a previous aborted allocation), then we +; are done. In both cases, we use the found entry. +; +lru2: + cmp es:[di].sf_ref_count,0 + jz lru25 + cmp es:[di].sf_ref_count,sf_busy + jnz lru3 +; +; The entry is usable without further scan. Go and use it. +; +lru25: + MOV si,DI ; pos = i; + JMP lru11 ; goto got; +; +; See if the entry is for the network or for the sharer. +; +; If for the sharer or network then +; if the age < current minimum AND >= allowed minimum then +; this entry becomes current minimum +; +lru3: + TEST ES:[DI].sf_flags,sf_isnet ; if (!net[i] + JNZ lru35 +if installed + Invoke CheckShare ; && !sharing) + JZ lru5 ; else +ENDIF +; +; This SFT is for the net or is for the sharer. See if it less than the +; current minimum. +; +lru35: + MOV DX,ES:[DI].sf_OpenAge + CMP DX,AX ; if (age[i] >= low && + JB lru5 + CMP DX,BX + JAE lru5 ; age[i] < min) { +; +; entry is new minimum. Remember his age. +; + mov bx,DX ; min = age[i]; + mov si,di ; pos = i; +; +; End of loop. gp back for more +; +lru5: +add di,size sf_entry + loop lru2 ; } +; +; The scan is complete. If we have successfully found a new minimum (pos != -1) +; set then threshold value to this new minimum + 1. Otherwise, the scan is +; complete. Go find LRU. +; +lru6: cmp si,-1 ; position not -1? + jz lru75 ; no, done with everything + lea ax,[bx+1] ; set new threshold age + jmp lru1 ; go and loop for more +lru65: stc + jmp short lruDead ; return -1; +; +; Main loop is done. We have AX being the age+1 of the nth oldest sharer or +; network entry. We now make a second pass through to find the LRU entry +; that is local-no-share or has age >= AX +; +lru75: + mov bx,-1 ; min = 0xffff; + mov si,bx ; pos = 0xffff; + LES DI,SFTFCB ; for (CX=FCBCount; CX>0; CX--) + MOV CX,ES:[DI].sfCount + LEA DI,[DI].sfTable +; +; If this is is local-no-share then go check for LRU else if age >= threshold +; then check for lru. +; +lru8: + TEST ES:[DI].sf_flags,sf_isnet + jnz lru85 ; is for network, go check age + invoke CheckShare ; sharer here? + jz lru86 ; no, go check lru +; +; Network or sharer. Check age +; +lru85: + cmp es:[di].sf_OpenAge,ax + jb lru9 ; age is before threshold, skip it +; +; Check LRU +; +lru86: + cmp es:[di].sf_LRU,bx ; is LRU less than current LRU? + jae lru9 ; no, skip this + mov si,di ; remember position + mov bx,es:[di].sf_LRU ; remember new minimum LRU +; +; Done with this entry, go back for more. +; +lru9: + add di,size sf_entry + loop lru8 +; +; Scan is complete. If we found NOTHING that satisfied us then we bomb +; out. The conditions here are: +; +; No local-no-shares AND all net/share entries are older than threshold +; +lru10: + cmp si,-1 ; if no one f + jz lru65 ; return -1; +lru11: + mov di,si + MOV WORD PTR ThisSFT,DI ; set thissft + MOV WORD PTR ThisSFT+2,ES +; +; If we have sharing or thisSFT is a net sft, then close it until ref count +; is 0. +; + TEST ES:[DI].sf_flags,sf_isNet + JNZ LRUClose +IF INSTALLED + Invoke CheckShare + JZ LRUDone +ENDIF +; +; Repeat close until ref count is 0 +; +LRUClose: + Context DS + LES DI,ThisSFT + CMP ES:[DI].sf_ref_count,0 ; is ref count still <> 0? + JZ LRUDone ; nope, all done + +; Message 1,"LRUFCB: closing " +; MessageNum +; Message 1,":" +; MessageNum + + Invoke DOS_Close + jnc LRUClose ; no error => clean up + cmp al,error_invalid_handle + jz LRUClose + stc + JMP short LRUDead +LRUDone: + XOR AL,AL + invoke BlastSFT ; fill SFT with 0 (AL) +LRUDead: + Invoke Restore_World + ASSUME DS:NOTHING + LES DI,ThisSFT + Assert ISSFT,,"LRUFCB return" + retnc + MOV AL,error_FCB_unavailable + return +EndProc LRUFCB + +Break + +; +; FCBRegen - examine reserved field of FCB and attempt to generate the SFT +; from it. +; +; Inputs: DS:SI point to FCB +; Outputs: carry clear Filled in SFT +; Carry set unrecoverable error +; Registers modified: all + +Procedure FCBRegen,NEAR + ASSUME DS:NOTHING,ES:NOTHING +; +; General data filling. Mode is sf_isFCB + open_for_both, date/time we do +; not fill, size we do no fill, position we do not fill, +; bit 14 of flags = TRUE, other bits = FALSE +; + MOV AL,[SI].fcb_l_drive +; +; We discriminate based on the first two bits in the reserved field. +; + TEST AL,FCBSPECIAL ; check for no sharing test + JZ RegenNoSharing ; yes, go regen from no sharing +; +; The FCB is for a network or a sharing based system. At this point we have +; already closed the SFT for this guy and reconnection is impossible. +; +; Remember that he may have given us a FCB with bogus information in it. +; Check to see if sharing is present or if the redir is present. If either is +; around, presume that we have cycled out the FCB and give the hard error. +; Otherwise, just return with carry set. +; + invoke CheckShare ; test for sharer + JNZ RegenFail ; yep, fail this. + MOV AX,multNet SHL 8 ; install check on multnet + INT 2FH + OR AL,AL ; is it there? + JZ RegenDead ; no, just fail the operation +RegenFail: + MOV AX,User_In_AX + cmp AH,fcb_close + jz RegenDead + invoke FCBHardErr ; massive hard error. +RegenDead: + STC + return ; carry set +; +; Local FCB without sharing. Check to see if sharing is loaded. If so +; fail the operation. +; +RegenNoSharing: + invoke CheckShare ; Sharing around? + JNZ RegenFail +; +; Find an SFT for this guy. +; + invoke LRUFcb + retc + MOV ES:[DI].sf_mode,SF_IsFCB + open_for_both + sharing_compat + AND AL,3Fh ; get drive number for flags + CBW + OR AX,sf_close_noDate ; normal FCB operation +; +; The bits field consists of the upper two bits (dirty and device) from the +; SFT and the low 4 bits from the open mode. +; + MOV CL,[SI].FCB_nsl_bits ; stick in dirty bits. + MOV CH,CL + AND CH,0C0h ; mask off the dirty/device bits + OR AL,CH + AND CL,access_mask ; get the mode bits + MOV BYTE PTR ES:[DI].sf_mode,CL + MOV ES:[DI].sf_flags,AX ; initial flags + MOV AX,Proc_ID + MOV ES:[DI].sf_PID,AX + SaveReg + Context ES + MOV DI,OFFSET DOSGroup:Name1 + MOV CX,8 + INC SI ; Skip past drive byte to name in FCB +RegenCopyName2: + LODSB + + IF DBCS ;AN000; + invoke testkanj ;AN000; + jz notkanj9 ;AN000; + STOSB ;AN000; + DEC CX ;AN000; + JCXZ DoneNam2 ;AN000; ; Ignore split kanji char error + LODSB ;AN000; + jmp short StuffChar2 ;AN000; + ;AN000; +notkanj9: ;AN000; + ENDIF ;AN000; + + Invoke UCase +StuffChar2: + STOSB + LOOP RegenCopyName2 +DoneNam2: + Context DS + MOV [ATTRIB],attr_hidden + attr_system + attr_directory + ; Must set this to something interesting + ; to call DEVNAME. + Invoke DevName ; check for device + ASSUME DS:NOTHING,ES:NOTHING + RestoreReg + JC RegenFileNoSharing ; not found on device list => file +; +; Device found. We can ignore disk-specific info +; + MOV BYTE PTR ES:[DI].sf_flags,BH ; device parms + MOV ES:[DI].sf_attr,0 ; attribute + LDS SI,DEVPT ; get device driver + MOV WORD PTR ES:[DI].sf_devptr,SI + MOV WORD PTR ES:[DI].sf_devptr+2,DS + return ; carry is clear + +RegenDeadJ: + JMP RegenDead +; +; File found. Just copy in the remaining pieces. +; +RegenFileNoSharing: + MOV AX,ES:[DI].sf_flags + AND AX,03Fh + SaveReg + Invoke Find_DPB + MOV WORD PTR ES:[DI].sf_devptr,SI + MOV WORD PTR ES:[DI].sf_devptr+2,DS + RestoreReg + jc RegenDeadJ ; if find DPB fails, then drive + ; indicator was bogus + MOV AX,[SI].FCB_nsl_dirsec + MOV WORD PTR ES:[DI].sf_dirsec,AX + MOV WORD PTR ES:[DI].sf_dirsec+2,0 ;AN000;>32mb + MOV AX,[SI].FCB_nsl_firclus + MOV ES:[DI].sf_firclus,AX + MOV ES:[DI].sf_lstclus,AX + MOV AL,[SI].FCB_nsl_dirpos + MOV ES:[DI].sf_dirpos,AL + INC ES:[DI].sf_ref_count ; Increment reference count. + ; Existing FCB entries would be + ; flushed unnecessarily because of + ; check in CheckFCB of the ref_count. + ; July 22/85 - BAS + LEA SI,[SI].FCB_name + LEA DI,[DI].sf_name + MOV CX,fcb_extent-fcb_name +RegenCopyName: + LODSB + + IF DBCS ;AN000; + invoke testkanj + jz notkanj1 + STOSB + DEC CX + JCXZ DoneNam ; Ignore split kanji char error + LODSB + jmp short StuffChar + +notkanj1: + ENDIF ;AN000; + + Invoke UCase +StuffChar: + STOSB + LOOP RegenCopyName +DoneNam: + clc + return +EndProc FCBRegen + +; +; BlastSFT - fill SFT with garbage +; +; Inputs: ES:DI point to SFT +; AL has fill +; Outputs: SFT is filled with nonsense +; *FLAGS PRESERVED* +; Registers modified: CX + +Procedure BlastSFT,NEAR + SaveReg + MOV CX,SIZE sf_entry + REP STOSB + RestoreReg + MOV ES:[DI].sf_ref_count,0 ; set ref count + MOV ES:[DI].sf_LRU,0 ; set lru + MOV ES:[DI].sf_OpenAge,-1 ; Set open age + return +EndProc BlastSFT + +Break + +; CheckFCB - examine an FCB and its contents to see if it needs to be +; regenerated. +; +; Inputs: DS:SI point to FCB (not extended) +; AL is SFT index +; Outputs: Carry Set - FCB needs to be regened +; Carry clear - FCB is OK. ES:DI point to SFT +; Registers modified: AX and BX + +Procedure CheckFCB,NEAR + ASSUME DS:NOTHING,ES:NOTHING + LES DI,sftFCB + CMP BYTE PTR ES:[DI].SFCount,AL + JC BadSFT + MOV BL,SIZE sf_entry + MUL BL + LEA DI,[DI].sftable + ADD DI,AX + MOV AX,Proc_ID + CMP ES:[DI].sf_PID,AX + JNZ BadSFT ; must match process + CMP ES:[DI].sf_ref_count,0 + JZ BadSFT ; must also be in use + MOV AL,[SI].FCB_l_Drive + TEST AL,FCBSPECIAL ; a special FCB? + JZ CheckNoShare ; No. try local or device +; +; Since we are a special FCB, try NOT to use a bogus test instruction. +; FCBSHARE is a superset of FCBNETWORK. +; + PUSH AX + AND AL,FCBMASK + CMP AL,FCBSHARE ; net FCB? + POP AX + JNZ CheckNet ; yes +; +;----- In share support ----- +; +if installed + Call JShare + 11 * 4 +else + Call ShChk +endif + JC BadSFT + JMP SHORT CheckD +; +;----- End in share support ----- +; +CheckFirClus: + CMP BX,ES:[DI].sf_firclus + JNZ BadSFT +CheckD: AND AL,3Fh + MOV AH,BYTE PTR ES:[DI].sf_flags + AND AH,3Fh + CMP AH,AL + retz ; carry is clear +BadSFT: STC + return ; carry is clear +CheckNet: +; +;----- In net support ----- +; +; MOV AX,[SI].FCB_net_handle +; CMP AX,WORD PTR ES:[DI].sf_NETID+4 +; JNZ BadSFT +; MOV AX,WORD PTR [SI].FCB_netID +; CMP AX,WORD PTR ES:[DI].sf_netid +; JNZ BadSFT + MOV AX,WORD PTR [SI].FCB_netID ;AN000;IFS.DOS 4.00 + CMP AX,WORD PTR ES:[DI].sf_serial_ID ;AN000;IFS.DOS 4.00 + JNZ BadSFT +; +;----- END In net support ----- +; + return + +CheckNoShare: + TEST AL,FCBDEVICE ; Device? + JNZ CheckNoShareDev ; Yes +; +; Check no sharing local file +; + MOV BX,[SI].FCB_nsl_Dirsec + CMP WORD PTR ES:[DI].sf_dirsec+2,0 ;AN000;F.C. >32mb + JNZ BadSFt ;AN000;F.C. >32mb + + CMP BX,WORD PTR ES:[DI].sf_dirsec ;AN000;F.C. >32mb + JNZ BadSFT + MOV BL,[SI].FCB_nsl_Dirpos + CMP BL,ES:[DI].sf_dirpos + JNZ BadSFt +; +; Since the bits field comes from two different spots, compare them separately. +; + MOV BL,[SI].FCB_nsl_bits + MOV BH,BYTE PTR ES:[DI].sf_flags + XOR BH,BL + AND BH,0C0h + JNZ BadSFT ; dirty/device bits are different + XOR BL,BYTE PTR ES:[DI].sf_mode + AND BL,access_mask + JNZ BadSFT ; access modes are different +; Make sure that the names are the same in the FCB and the SFT +; This case can appear under the following scenario: +; Create FOO +; Rename FOO -> BAR +; Open BAR +; The SFT will still contain the name for the old file name. +; July 30/85 - BAS + PUSH DI + PUSH SI + LEA DI,[DI].sf_name + LEA SI,[SI].fcb_name + MOV CX,11 + REPE CMPSB + POP SI + POP DI + JNZ BadSFT + MOV BX,[SI].FCB_nsl_firclus + JMP CheckFirClus + +CheckNoShareDev: + MOV BX,WORD PTR [SI].FCB_nsld_drvptr + CMP BX,WORD PTR ES:[DI].sf_devptr + JNZ BadSFT + MOV BX,WORD PTR [SI].FCB_nsld_drvptr + 2 + CMP BX,WORD PTR ES:[DI].sf_devptr + 2 + JNZ BadSFT + JMP CheckD + +EndProc CheckFCB + +Break + +; +; SFTFromFCB - the workhorse of this compatability crap. Check to see if +; the SFT for the FCB is Good. If so, make ThisSFT point to it. If not +; good, get one from the cache and regenerate it. Overlay the LRU field +; with PID +; +; Inputs: DS:SI point to FCB +; Outputs: ThisSFT point to appropriate SFT +; Carry clear -> OK ES:DI -> SFT +; Carry set -> error in ax +; Registers modified: ES,DI, AX + +Procedure SFTFromFCB,NEAR + ASSUME DS:NOTHING,ES:NOTHING + SaveReg + MOV AL,[SI].fcb_sfn ; set SFN for check + invoke CheckFCB + RestoreReg + MOV WORD PTR ThisSFT,DI ; set thissft + MOV WORD PTR ThisSFT+2,ES + JNC SetSFT ; no problems, just set thissft + + fmt typFCB,LevCheck,<"FCB $x:$x does not match SFT $x:$x\n">, + + Invoke Save_World + invoke FCBRegen + Invoke Restore_World ; restore world + MOV AX,EXTERR + retc + +; Message 1,<"FCBRegen Succeeded",13,10> + +SetSFT: LES DI,ThisSFT + PUSH Proc_ID ; set process id + POP ES:[DI].sf_PID + return ; carry is clear +EndProc SFTFromFCB + +Break + +; +; FCBHardErr - signal to a user app that he is trying to use an +; unavailable FCB. +; +; Inputs: none. +; Outputs: none. +; Registers modified: all +; + +Procedure FCBHardErr,NEAR + ASSUME DS:NOTHING,ES:NOTHING + MOV AX,error_FCB_Unavailable + MOV [ALLOWED],allowed_FAIL + LES BP,[THISDPB] + MOV DI,1 ; Fake some registers + MOV CX,DI + MOV DX,ES:[BP.dpb_first_sector] + invoke HARDERR + STC + return +EndProc FCBHardErr + +CODE ENDS +END diff --git a/v4.0/src/DOS/FCBIO2.ASM b/v4.0/src/DOS/FCBIO2.ASM new file mode 100644 index 0000000..ec0ee3e --- /dev/null +++ b/v4.0/src/DOS/FCBIO2.ASM @@ -0,0 +1,722 @@ +; SCCSID = @(#)fcbio2.asm 1.2 85/07/23 +; SCCSID = @(#)fcbio2.asm 1.2 85/07/23 +TITLE FCBIO2 - FCB system calls +NAME FCBIO2 + +; +; Ancient 1.0 1.1 FCB system calls +; regen save +; GetRR +; GetExtent +; SetExtent +; GetExtended +; GetRecSize +; FCBIO +; $FCB_OPEN written ACC ACC +; $FCB_CREATE written ACC ACC +; $FCB_RANDOM_WRITE_BLOCK written fcbio fcbio +; $FCB_RANDOM_READ_BLOCK written fcbio fcbio +; $FCB_SEQ_READ written fcbio fcbio +; $FCB_SEQ_WRITE written fcbio fcbio +; $FCB_RANDOM_READ written fcbio fcbio +; $FCB_RANDOM_WRITE written fcbio fcbio +; +; Revision history: +; +; Created: ARR 4 April 1983 +; MZ 6 June 1983 completion of functions +; MZ 15 Dec 1983 Brain damaged programs close FCBs multiple +; times. Change so successive closes work by +; always returning OK. Also, detect I/O to +; already closed FCB and return EOF. +; MZ 16 Jan 1984 More braindamage. Need to separate info +; out of sft into FCB for reconnection +; +; A000 version 4.00 Jan. 1988 +; +.xlist +; +; get the appropriate segment definitions +; +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +include version.inc +.cref +.list + + EXTRN DOS_Read:NEAR, DOS_Write:NEAR + EXTRN DOS_Open:NEAR, DOS_Create:NEAR + + I_need DMAAdd,DWORD ; current user's DMA address + I_need OpenBuf,128 ; buffer for translating paths + I_need ThisSFT,DWORD ; SFT in use + I_need sftFCB,DWORD ; pointer to SFTs for FCB cache + I_need FCBLRU,WORD ; least recently used count + I_need DISK_FULL,BYTE ; flag for disk full +if debug + I_need BugLev,WORD + I_need BugTyp,WORD + include bugtyp.asm +endif + +IF BUFFERFLAG + + I_need BUF_EMS_MODE,BYTE + I_need BUF_EMS_LAST_PAGE,DWORD + I_need BUF_EMS_FIRST_PAGE,DWORD + I_need BUF_EMS_SAFE_FLAG,BYTE + I_need BUF_EMS_NPA640,WORD + I_need BUF_EMS_PAGE_FRAME,WORD + I_need BUF_EMS_PFRAME,WORD + I_need LASTBUFFER,DWORD + + extrn restore_user_map:near + extrn Setup_EMS_Buffers:near + +ENDIF + + +; Defintions for FCBOp flags + +Random = 2 ; random operation +FCBRead = 4 ; doing a read +Block = 8 ; doing a block I/O + +Break + +; +; GetRR - correctly load DX:AX with the random record field (3 or 4 bytes) +; from the FCB pointed to by DS:SI +; +; Inputs: DS:SI point to an FCB +; BX has record size +; Outputs: DX:AX contain the contents of the random record field +; Registers modified: none + +Procedure GetRR,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP + MOV AX,WORD PTR [SI.FCB_RR] ; get low order part + MOV DX,WORD PTR [SI.FCB_RR+2] ; get high order part + CMP BX,64 ; ignore MSB of RR if recsiz > 64 + JB GetRRBye + XOR DH,DH +GetRRBye: + return +EndProc GetRR + +Break + +; +; GetExtent - Construct the next record to perform I/O from the EXTENT and +; NR fields in the FCB. +; +; Inputs: DS:SI - point to FCB +; Outputs: DX:AX contain the contents of the random record field +; Registers modified: none + +Procedure GetExtent,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP + MOV AL,[SI.fcb_NR] ; get low order piece + MOV DX,[SI.fcb_EXTENT] ; get high order piece + SHL AL,1 + SHR DX,1 + RCR AL,1 ; move low order bit of DL to high order of AH + MOV AH,DL + MOV DL,DH + XOR DH,DH + return +EndProc GetExtent + +Break + +; +; SetExtent - change the position of an FCB by filling in the extent/NR +; fields +; +; Inputs: DS:SI point to FCB +; DX:AX is a record location in file +; Outputs: Extent/NR fields are filled in +; Registers modified: CX + +Procedure SetExtent,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup + SaveReg + MOV CX,AX + AND AL,7FH ; next rec field + MOV [SI.fcb_NR],AL + AND CL,80H ; save upper bit + SHL CX,1 + RCL DX,1 ; move high bit of CX to low bit of DX + MOV AL,CH + MOV AH,DL + MOV [SI.fcb_EXTENT],AX ; all done + RestoreReg + return +EndProc SetExtent + +Break + +; +; GetExtended - Make DS:SI point to FCB from DS:DX +; +; Inputs: DS:DX point to a possible extended FCB +; Outputs: DS:SI point to the FCB part +; zeroflag set if not extended fcb +; Registers modified: SI + +Procedure GetExtended,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP + MOV SI,DX ; point to Something + CMP BYTE PTR DS:[SI],-1 ; look for extention + JNZ GetBye ; not there + ADD SI,7 ; point to FCB +GetBye: + CMP SI,DX ; set condition codes + return +EndProc GetExtended + +Break + +; +; GetRecSize - return in BX the record size from the FCB at DS:SI +; +; Inputs: DS:SI point to a non-extended FCB +; Outputs: BX contains the record size +; Registers modified: None + +Procedure GetRecSize,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup + MOV BX,[SI.fcb_RECSIZ] ; get his record size + OR BX,BX ; is it nul? + retnz + MOV BX,128 ; use default size + MOV [SI.fcb_RECSIZ],BX ; stuff it back + return +EndProc GetRecSize + +BREAK + +; +; FCBIO - look at FCBOP and merge all FCB operations into a single routine. +; +; Inputs: FCBOP flags which operations need to be performed +; DS:DX point to FCB +; CX may have count of number of records to xfer +; Outputs: AL has error code +; Registers modified: all + +Procedure FCBIO,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup +PUBLIC FCBIO001S,FCBIO001E +FCBIO001S: + LocalVar FCBErr,BYTE + LocalVar cRec,WORD + LocalVar RecPos,DWORD + LocalVar RecSize,WORD + LocalVar bPos,DWORD + LocalVar cByte,WORD + LocalVar cResult,WORD + LocalVar cRecRes,WORD + LocalVar FCBOp,BYTE +FCBIO001E: + Enter + +FEOF EQU 1 +FTRIM EQU 2 + MOV FCBOp,AL + MOV FCBErr,0 ; FCBErr = 0; + invoke GetExtended ; FCB = GetExtended (); + TEST FCBOp,BLOCK ; if ((OP&BLOCK) == 0) + JNZ GetPos + MOV CX,1 ; cRec = 1; +GetPos: + MOV cRec,CX ;*Tail coalesce + invoke GetExtent ; RecPos = GetExtent (); + invoke GetRecSize ; RecSize = GetRecSize (); + MOV RecSize,BX + TEST FCBOp,RANDOM ; if ((OP&RANDOM) <> 0) + JZ GetRec + invoke GetRR ; RecPos = GetRR (); +GetRec: + MOV RecPosL,AX ;*Tail coalesce + MOV RecPosH,DX + invoke SetExtent ; SetExtent (RecPos); + MOV AX,RecPosH ; bPos = RecPos * RecSize; + MUL BX + MOV DI,AX + MOV AX,RecPosL + MUL BX + ADD DX,DI + MOV bPosL,AX + MOV bPosH,DX + MOV AX,cRec ; cByte = cRec * RecSize; + MUL BX + MOV cByte,AX + ADD AX,WORD PTR DMAAdd ; if (cByte+DMA > 64K) { + ADC DX,0 + JZ DoOper + MOV FCBErr,FTRIM ; FCBErr = FTRIM; + MOV AX,WORD PTR DMAAdd ; cRec = (64K-DMA)/RecSize; + NEG AX + JNZ DoDiv + DEC AX +DoDiv: + XOR DX,DX + DIV BX + MOV cRec,AX + MUL BX ; cByte = cRec * RecSize; + MOV cByte,AX ; } +DoOper: + XOR BX,BX + MOV cResult,BX ; cResult = 0; + CMP cByte,BX ; if (cByte <> 0 || + JNZ DoGetExt + TEST FCBErr,FTRIM ; (FCBErr&FTRIM) == 0) { +IF debug + JZ DoGetExt + JMP SkipOp +ELSE + JZ SKP_SkipOp + JMP SkipOp +SKP_SkipOp: +ENDIF +DoGetExt: + invoke SFTFromFCB ; if (!SFTFromFCB (SFT,FCB)) + JNC ContinueOp +FCBDeath: + invoke FCB_Ret_Err ; signal error, map for extended + MOV cRecRes,0 ; no bytes transferred + MOV FCBErr,FEOF ; return FTRIM; + JMP FCBSave ; bam! +ContinueOp: + Assert ISSFT,,"ContinueOP" + MOV AX,WORD PTR [SI].fcb_filsiz + MOV WORD PTR ES:[DI].sf_size,AX + MOV AX,WORD PTR [SI].fcb_filsiz+2 + MOV WORD PTR ES:[DI].sf_size+2,AX + MOV AX,bPosL + MOV DX,bPosH + MOV WORD PTR ES:[DI.sf_position],AX + XCHG WORD PTR ES:[DI.sf_position+2],DX + PUSH DX ; save away Open age. + MOV CX,cByte ; cResult = + +; int 3 + + MOV DI,OFFSET DOSGroup:DOS_Read ; *(OP&FCBRead ? DOS_Read + TEST FCBOp,FCBRead ; : DOS_Write)(cRec); + JNZ DoContext + MOV DI,OFFSET DOSGroup:DOS_Write +DoContext: + SaveReg + Context DS +;; Fix for disk full + CALL DI + RestoreReg + ASSUME DS:NOTHING + +IF BUFFERFLAG + pushf + push ax + push bx + + cmp cs:[BUF_EMS_MODE], -1 + jz dos_fcb_call_done + call restore_user_map + mov ax, word ptr cs:[BUF_EMS_LAST_PAGE] + cmp cs:[BUF_EMS_PFRAME], ax + je dos_fcb_call_done + mov word ptr cs:[LASTBUFFER], -1 + mov cs:[BUF_EMS_PFRAME], ax + mov ax, word ptr cs:[BUF_EMS_LAST_PAGE+2] + mov cs:[BUF_EMS_PAGE_FRAME], ax + mov cs:[BUF_EMS_SAFE_FLAG], 1 + call Setup_EMS_Buffers + +dos_fcb_call_done: + pop bx + pop ax + popf +ENDIF + + JC FCBDeath + + CMP BYTE PTR [DISK_FULL],0 ; treat disk full as error + JZ NODSKFULL + MOV BYTE PTR [DISK_FULL],0 ; clear the flag + MOV FCBerr,FEOF ; set disk full flag +NODSKFULL: +;; Fix for disk full + MOV cResult,CX + invoke SaveFCBInfo ; SaveFCBInfo (FCB); + Assert ISSFT,,"FCBIO/SaveFCBInfo" +%out WARNING!!! Make sure sf_position+2 is OpenAGE + POP WORD PTR ES:[DI].sf_Position+2 ; restore open age + MOV AX,WORD PTR ES:[DI].sf_size + MOV WORD PTR [SI].fcb_filsiz,AX + MOV AX,WORD PTR ES:[DI].sf_size+2 + MOV WORD PTR [SI].fcb_filsiz+2,AX + ; } +SkipOp: + MOV AX,cResult ; cRecRes = cResult / RecSize; + XOR DX,DX + DIV RecSize + MOV cRecRes,AX + ADD RecPosL,AX ; RecPos += cRecResult; + ADC RecPosH,0 +; +; If we have not gotten the expected number of records, we signal an EOF +; condition. On input, this is EOF. On output this is usually disk full. +; BUT... Under 2.0 and before, all device output IGNORED this condition. So +; do we. +; + CMP AX,cRec ; if (cRecRes <> cRec) + JZ TryBlank + TEST FCBOp,FCBRead ; if (OP&FCBRead || !DEVICE) + JNZ SetEOF + TEST ES:[DI].sf_flags,devid_device + JNZ TryBlank +SetEOF: + MOV FCBErr,FEOF ; FCBErr = FEOF; +TryBlank: ; + OR DX,DX ; if (cResult%RecSize <> 0) { + JZ SetExt + ADD RecPosL,1 ; RecPos++; + ADC RecPosH,0 + TEST FCBOp,FCBRead ; if(OP&FCBRead) <> 0) { + JZ SetExt + INC cRecRes ; cRecRes++; + MOV FCBErr,FTRIM + FEOF ; FCBErr = FTRIM | FEOF; + MOV CX,RecSize ; Blank (RecSize-cResult%RecSize, + SUB CX,DX ; DMA+cResult); + XOR AL,AL + LES DI,DMAAdd + ADD DI,cResult + REP STOSB ; } } +SetExt: + MOV DX,RecPosH + MOV AX,RecPosL + TEST FCBOp,RANDOM ; if ((OP&Random) == 0 || + JZ DoSetExt + TEST FCBOp,BLOCK ; (OP&BLOCK) <> 0) + JZ TrySetRR +DoSetExt: + invoke SetExtent ; SetExtent (RecPos, FCB); +TrySetRR: + TEST FCBOp,BLOCK ; if ((op&BLOCK) <> 0) + JZ TryReturn + MOV WORD PTR [SI.FCB_RR],AX ; FCB->RR = RecPos; + MOV BYTE PTR [SI.FCB_RR+2],DL + CMP [SI.fcb_RECSIZ],64 + JAE TryReturn + MOV [SI+fcb_RR+2+1],DH ; Set 4th byte only if record size < 64 +TryReturn: + TEST FCBOP,FCBRead ; if (!(FCBOP & FCBREAD)) { + JNZ FCBSave + SaveReg ; FCB->FDate = date; + Invoke Date16 ; FCB->FTime = time; + RestoreReg + MOV [SI].FCB_FDate,AX + MOV [SI].FCB_FTime,DX ; } +FCBSave: + TEST FCBOp,BLOCK ; if ((op&BLOCK) <> 0) + JZ DoReturn + MOV CX,cRecRes ; user_CX = cRecRes; + invoke Get_User_Stack + MOV [SI.User_CX],CX +DoReturn: + MOV AL,FCBErr ; return (FCBERR); + Leave + return +EndProc FCBIO + +Break <$FCB_Open - open an old-style FCB> + +; +; $FCB_Open - CPM compatability file open. The user has formatted an FCB +; for us and asked to have the rest filled in. +; +; Inputs: DS:DX point to an unopenned FCB +; Outputs: AL indicates status 0 is ok FF is error +; FCB has the following fields filled in: +; Time/Date Extent/NR Size + +Procedure $FCB_Open,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP + MOV AX,sharing_Compat+Open_For_Both + MOV CX,OFFSET DOSGroup:DOS_Open +; +; The following is common code for Creation and openning of FCBs. AX is +; either attributes (for create) or open mode (for open)... DS:DX points to +; the FCB +; +DoAccess: + SaveReg ; save FCB pointer away + MOV DI,OFFSET DOSGroup:OpenBuf + invoke TransFCB ; crunch the fcb + RestoreReg ; get fcb + JNC FindFCB ; everything seems ok +FCBOpenErr: +; +; AL has error code +; + transfer FCB_Ret_Err +FindFCB: + invoke GetExtended ; DS:SI will point to FCB + invoke LRUFCB ; get a sft entry (no error) + JC HardMessage + ASSUME ES:NOTHING + +; Message 1,"Entering " +; MessageNum ES +; Message 1,":" +; MessageNum DI +; Message 1,<13,10> + + MOV ES:[DI].sf_mode,sf_ISFCB + SaveReg ; save fcb pointer + MOV SI,CX + Context DS ; let DOS_Open see variables + CALL SI ; go open the file + RestoreReg ; get fcb + ASSUME DS:NOTHING + LES DI,ThisSFT ; get sf pointer + JNC FCBOK ; operation succeeded + Assert ISSFT,,"DeadFCB" +failopen: + PUSH AX + MOV AL,"R" ; clear out field (free sft) + invoke BlastSFT + POP AX + CMP AX,error_too_many_open_files + JZ HardMessage + CMP AX,error_sharing_buffer_exceeded + jnz DeadFCB +HardMessage: + PUSH AX + invoke FCBHardErr + POP AX +DeadFCB: + transfer FCB_Ret_Err +FCBOK: + invoke IsSFTNet ;AN007;F.C. >32mb Non Fat file? + JNZ FCBOK2 ;AN007;F.C. >32mb yes + invoke CheckShare ;AN000;F.C. >32mb share around? + JNZ FCBOK2 ;AN000;F.C. >32mb yes + CMP WORD PTR ES:[DI].sf_dirsec+2,0 ;AN000;F.C. >32mb if dirsec >32mb + JZ FCBOK2 ;AN000;F.C. >32mb then error + MOV AX,error_sys_comp_not_loaded ;AN000;F.C. >32mb + JMP failopen ;AN000;F.C. >32mb +FCBOK2: + + INC ES:[DI].sf_ref_count ; increment reference count + invoke SaveFCBInfo + Assert ISSFT,,"FCBOK" + invoke SetOpenAge + Assert ISSFT,,"FCBOK/SetOpenAge" + TEST ES:[DI].sf_flags,devid_device + JNZ FCBNoDrive ; do not munge drive on devices + MOV AL,DS:[SI] ; get drive byte + invoke GetThisDrv ; convert + INC AL + MOV DS:[SI],AL ; stash in good drive letter +FCBNoDrive: + MOV [SI].FCB_RecSiz,80h ; stuff in default record size + MOV AX,ES:[DI].SF_Time ; set time + MOV [SI].FCB_FTime,AX + MOV AX,ES:[DI].SF_Date ; set date + MOV [SI].FCB_FDate,AX + MOV AX,WORD PTR ES:[DI].SF_Size ; set sizes + MOV [SI].FCB_FILSIZ,AX + MOV AX,WORD PTR ES:[DI].SF_Size+2 + MOV [SI].FCB_FILSIZ+2,AX + XOR AX,AX ; convenient zero + MOV [SI].FCB_Extent,AX ; point to beginning of file +; +; We must scan the set of FCB SFTs for one that appears to match the current +; one. We cheat and use CheckFCB to match the FCBs. +; + LES DI,SFTFCB ; get the pointer to head of the list + MOV AH,BYTE PTR ES:[DI].sfCount ; get number of SFTs to scan +OpenScan: + CMP AL,[SI].fcb_sfn ; don't compare ourselves + JZ SkipCheck + SaveReg ; preserve count + invoke CheckFCB ; do they match + RestoreReg ; get count back + JNC OpenFound ; found a match! +SkipCheck: + INC AL ; advance to next FCB + CMP AL,AH ; table full? + JNZ OpenScan ; no, go for more +OpenDone: + xor al,al ; return success + return +; +; The SFT at ES:DI is the one that is already in use for this FCB. We set the +; FCB to use this one. We increment its ref count. We do NOT close it at all. +; Consider: +; +; open (foo) delete (foo) open (bar) +; +; This causes us to recycle (potentially) bar through the same local SFT as +; foo even though foo is no longer needed; this is due to the server closing +; foo for us when we delete it. Unfortunately, we cannot see this closure. +; If we were to CLOSE bar, the server would then close the only reference to +; bar and subsequent I/O would be lost to the redirector. +; +; This gets solved by NOT closing the sft, but zeroing the ref count +; (effectively freeing the SFT) and informing the sharer (if relevant) that +; the SFT is no longer in use. Note that the SHARER MUST keep its ref counts +; around. This will allow us to access the same file through multiple network +; connections and NOT prematurely terminate when the ref count on one +; connection goes to zero. +; +OpenFound: + MOV [SI].fcb_SFN,AL ; assign with this + INC ES:[DI].sf_ref_count ; remember this new invocation + MOV AX,FCBLRU ; update LRU counts + MOV ES:[DI].sf_LRU,AX +; +; We have an FCB sft that is now of no use. We release sharing info and then +; blast it to prevent other reuse. +; + context DS + LES DI,ThisSFT + DEC ES:[DI].sf_ref_count ; free the newly allocated SFT + invoke ShareEnd + Assert ISSFT,,"Open blasting" + MOV AL,'C' + invoke BlastSFT + JMP OpenDone +EndProc $FCB_Open + +BREAK <$FCB_Create - create a new directory entry> + +; +; $FCB_Create - CPM compatability file create. The user has formatted an +; FCB for us and asked to have the rest filled in. +; +; Inputs: DS:DX point to an unopenned FCB +; Outputs: AL indicates status 0 is ok FF is error +; FCB has the following fields filled in: +; Time/Date Extent/NR Size + +Procedure $FCB_Create,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup + MOV CX,OFFSET DOSGroup:DOS_Create ; routine to call + XOR AX,AX ; attributes to create + invoke GetExtended ; get extended FCB + JZ DoAccessJ ; not an extended FCB + MOV AL,[SI-1] ; get attributes +DoAccessJ: + JMP DoAccess ; do dirty work +EndProc $FCB_Create + +BREAK <$FCB_Random_write_Block - write a block of records to a file > + +; +; $FCB_Random_Write_Block - retrieve a location from the FCB, seek to it +; and write a number of blocks from it. +; +; Inputs: DS:DX point to an FCB +; Outputs: AL = 0 write was successful and the FCB position is updated +; AL <> 0 Not enough room on disk for the output +; + +Procedure $FCB_Random_Write_Block,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup + MOV AL,Random+Block + JMP FCBIO +EndProc $FCB_Random_Write_Block + +BREAK <$FCB_Random_Read_Block - read a block of records to a file > + +; +; $FCB_Random_Read_Block - retrieve a location from the FCB, seek to it +; and read a number of blocks from it. +; +; Inputs: DS:DX point to an FCB +; Outputs: AL = error codes defined above +; + +Procedure $FCB_Random_Read_Block,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup + MOV AL,Random+FCBRead+Block + JMP FCBIO +EndProc $FCB_Random_Read_Block + +BREAK <$FCB_Seq_Read - read the next record from a file > + +; +; $FCB_Seq_Read - retrieve the next record from an FCB and read it into +; memory +; +; Inputs: DS:DX point to an FCB +; Outputs: AL = error codes defined above +; + +Procedure $FCB_Seq_Read,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup + MOV AL,FCBRead + JMP FCBIO +EndProc $FCB_Seq_Read + +BREAK <$FCB_Seq_Write - write the next record to a file > + +; +; $FCB_Seq_Write - retrieve the next record from an FCB and write it to the +; file +; +; Inputs: DS:DX point to an FCB +; Outputs: AL = error codes defined above +; + +Procedure $FCB_Seq_Write,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup + MOV AL,0 + jmp FCBIO +EndProc $FCB_SEQ_WRITE + +BREAK <$FCB_Random_Read - Read a single record from a file > + +; +; $FCB_Random_Read - retrieve a location from the FCB, seek to it and read a +; record from it. +; +; Inputs: DS:DX point to an FCB +; Outputs: AL = error codes defined above +; + +Procedure $FCB_Random_Read,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup + MOV AL,Random+FCBRead + jmp FCBIO ; single block +EndProc $FCB_RANDOM_READ + +BREAK <$FCB_Random_Write - write a single record to a file > + +; +; $FCB_Random_Write - retrieve a location from the FCB, seek to it and write +; a record to it. +; +; Inputs: DS:DX point to an FCB +; Outputs: AL = error codes defined above +; + +Procedure $FCB_Random_Write,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup + MOV AL,Random + jmp FCBIO +EndProc $FCB_RANDOM_WRITE + +CODE ENDS +END + + \ No newline at end of file diff --git a/v4.0/src/DOS/FILE.ASM b/v4.0/src/DOS/FILE.ASM new file mode 100644 index 0000000..9fca034 --- /dev/null +++ b/v4.0/src/DOS/FILE.ASM @@ -0,0 +1,909 @@ +; SCCSID = @(#)file.asm 1.2 85/07/23 +; SCCSID = @(#)file.asm 1.2 85/07/23 +TITLE FILE - Pathname related system calls +NAME FILE + +; +; Pathname related system calls. These will be passed direct text of the +; pathname from the user. They will need to be passed through the macro +; expander prior to being sent through the low-level stuff. I/O specs are +; defined in DISPATCH. The system calls are: +; +; $Open written +; $Creat written +; $ChMod written +; $Unlink written +; $Rename written +; $CreateTempFile written +; $CreateNewFile written +; $Extended_Open written DOS 4.00 +; GetIOParms written DOS 4.00 +; +; Revision history: +; +; Created: MZ 4 April 1983 +; A000 version 4.00 Jan. 1988 + +.xlist +; +; get the appropriate segment definitions +; +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGroup,CS:DOSGroup + +.xcref +include dossym.inc +include devsym.inc +include fastopen.inc +include EA.inc ;AN000; +include version.inc +.cref +.list +.sall + + EXTRN DOS_OPEN:NEAR,DOS_CREATE:NEAR,DOS_Create_New:NEAR + +IF NOT IBMCOPYRIGHT + extrn Set_EXT_mode:near +ENDIF + + I_need WFP_Start,WORD ; pointer to beginning of expansion + I_Need ThisCDS,DWORD ; pointer to curdir in use + I_need ThisSft,DWORD ; SFT pointer for DOS_Open + I_need pJFN,DWORD ; temporary spot for pointer to JFN + I_need JFN,WORD ; word JFN for process + I_need SFN,WORD ; word SFN for process + I_Need OpenBuf,128 ; buffer for filename + I_Need RenBuf,128 ; buffer for filename in rename + I_need Sattrib,BYTE ; byte attribute to search for + I_need Ren_WFP,WORD ; pointer to real path + I_need cMeta,BYTE + I_need EXTERR,WORD ; extended error code + I_need EXTERR_LOCUS,BYTE ; Extended Error Locus + i_need JShare,DWORD ; share jump table + I_need fSharing,BYTE ; TRUE => via ServerDOSCall + I_need FastOpenTable,BYTE + I_need CPSWFLAG,BYTE ;AN000;FT. cpsw falg + I_need EXTOPEN_FLAG,WORD ;AN000;FT. extended file open flag + I_need EXTOPEN_ON,BYTE ;AN000;FT. extended open flag + I_need EXTOPEN_IO_MODE,WORD ;AN000;FT. IO mode + I_need XA_from,BYTE ;AN000;;FT. for get/set XA + I_need SAVE_ES,WORD ;AN000;;FT. for get/set XA + I_need SAVE_DI,WORD ;AN000;;FT. for get/set XA + I_need SAVE_DS,WORD ;AN000;;FT. for get/set XA + I_need SAVE_SI,WORD ;AN000;;FT. for get/set XA + I_need SAVE_DX,WORD ;AN000;;FT. for get/set XA + I_need SAVE_BX,WORD ;AN000;;FT. for get/set XA + I_need SAVE_CX,WORD ;AN000;;FT. for get/set XA + I_need NO_FILTER_DPATH,DWORD ;AN000;; pointer to original path of dest + I_need Temp_Var,WORD ;AN000;; + I_need DOS34_FLAG,WORD ;AN000;; + I_need Temp_Var2,WORD ;AN000;; +if debug + I_need BugLev,WORD + I_need BugTyp,WORD +include bugtyp.asm +endif + +BREAK <$Open - open a file from a path string> + +; +; $Open - given a path name in DS:DX and an open mode in AL, access the file +; and return a handle +; Inputs: DS:DX - pointer to asciz name +; AL - open mode +; Outputs: Carry Set - AX has error code for invalid open +; Carry Clear - AX has per process handle number +; Registers modified: most + +Procedure $Open,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup + fmt TypSysCall,LevLog,<"Open\n"> + fmt TypSysCall,LevArgs,<" Mode = $x file = '$S'\n">, + XOR AH,AH +Entry $Open2 ;AN000; + mov ch,attr_hidden+attr_system+attr_directory + call SetAttrib + MOV CX,OFFSET DOSGroup:DOS_Open ; address of routine to call + SaveReg ; Save mode on stack +IF DBCS ;AN000; + MOV [Temp_Var],0 ;AN000;KK. set variable with 0 +ENDIF ;AN000; + +AccessFile: +; +; Grab a free SFT. +; +IF DBCS ;AN000; + TEST [Temp_Var],8 ;AN000;;KK. volume id bit set ;AN000; + JZ novol ;AN000;;KK. no ;AN000; + OR [DOS34_FLAG],DBCS_VOLID ;AN000;;KK. set bit for transpath ;AN000; +novol: ;AN000; +ENDIF ;AN000; + EnterCrit critSFT + invoke SFNFree ; get a free sfn + LeaveCrit critSFT + JC OpenFailJ ; oops, no free sft's + MOV SFN,BX ; save the SFN for later + fmt TypAccess,LevSFN,<"AccessFile setting SFN to $x\n">, + MOV WORD PTR [ThisSFT],DI ; save the SF offset + MOV WORD PTR [ThisSFT+2],ES ; save the SF segment +; +; Find a free area in the user's JFN table. +; + invoke JFNFree ; get a free jfn + JNC SaveJFN +OpenFailJ: + JMP OpenFail ; there were free JFNs... try SFN +SaveJFN: + MOV WORD PTR [pJFN],DI ; save the jfn offset + MOV WORD PTR [pJFN+2],ES ; save the jfn segment + MOV [JFN],BX ; save the jfn itself +; +; We have been given an JFN. We lock it down to prevent other tasks from +; reusing the same JFN. +; + MOV BX,SFN + MOV ES:[DI],BL ; assign the JFN + MOV SI,DX ; get name in appropriate place + MOV DI,OFFSET DOSGroup:OpenBuf ; appropriate buffer + SaveReg ; save routine to call + invoke TransPath ; convert the path + RestoreReg ; restore routine to call + LDS SI,ThisSFT + ASSUME DS:NOTHING + JC OpenCleanJ ; no error, go and open file + CMP cMeta,-1 + JZ SetSearch + MOV AL,error_file_not_found ; no meta chars allowed +OpenCleanJ: + JMP OpenClean +SetSearch: + RestoreReg ; Mode (Open), Attributes (Create) +; +; We need to get the new inheritance bits. +; + xor cx,cx + CMP BX,OFFSET DOSGroup:DOS_OPEN + JNZ DoOper + TEST AL,sharing_no_inherit ; look for no inher + JZ DoOper + AND AL,07Fh ; mask off inherit bit + MOV CX,sf_no_inherit +DoOper: + MOV [SI].sf_mode,0 ; initialize mode field to 0 + MOV [SI.SF_mft],0 ; clean out sharing info +; +;------------------------------------------------------------HKN 8/7/88 +; Check if this is an extended open. If so you must set the +; modes in sf_mode. Call Set_EXT_mode to do all this. See +; Set_EXT_mode in creat.asm +; +IF NOT IBMCOPYRIGHT + + push es ; set up es:di to point to SFT + push di + push ds + pop es + push si + pop di + call Set_EXT_mode + pop di + pop es + +ENDIF + +;----------------------------------------------------------------------- + + Context DS + SaveReg + CALL BX ; blam! + RestoreReg + LDS SI,ThisSFT + ASSUME DS:NOTHING + JC OpenE2 ;AN000;FT. chek extended open hooks first +; +; The SFT was successfully opened. Remove busy mark. +; +OpenOK: + ASSUME DS:NOTHING +; MOV AL,[SI].sf_attr_hi ;AN000;FT. save file type for EXEC +; MOV BYTE PTR [Temp_Var2],AL ;AN000;FT. + MOV [SI].sf_ref_count,1 + OR [SI].sf_flags,CX ; set no inherit bit if necessary +; +; If the open mode is 70, we scan the system for other SFT's with the same +; contents. If we find one, then we can 'collapse' thissft onto the already +; opened one. Otherwise we use this new one. We compare uid/pid/mode/mft +; +; Since this is only relevant on sharer systems, we stick this code into the +; sharer. +; + MOV AX,JFN +if installed + Call JShare + 12 * 4 +else + Call ShCol +endif + fmt TypAccess,LevSFN,<"AccessFile setting SFN to -1\n"> + MOV SFN,-1 ; clear out sfn pointer + fmt TypSysCall,LevLog,<"Open/CreateXX: return $x\n">, + transfer Sys_Ret_OK ; bye with no errors +;Extended Open hooks check +OpenE2: ;AN000;;EO. + CMP AX,error_invalid_parameter ;AN000;;EO. IFS extended open ? + JNZ OpenE ;AN000;;EO. no. + JMP OpenCritLeave ;AN000;;EO. keep handle + +;Extended Open hooks check +; +; AL has error code. Stack has argument to dos_open/dos_create. +; +OpenClean: + fmt TypSysCall,LevLog,<"Return value from transpath $x\n">, + RestoreReg ; clean off stack +OpenE: + MOV [SI.SF_Ref_Count],0 ; release SFT + LDS SI,pJFN + MOV BYTE PTR [SI],0FFh ; free the SFN... + JMP SHORT OpenCritLeave + +OpenFail: + STI + RestoreReg ; Clean stack +OpenCritLeave: + MOV SFN,-1 ; remove mark. + fmt TypSysCall,LevLog,<"Open/CreateXX: error $x\n">, +;; File Tagging DOS 4.00 + CMP CS:[EXTERR],error_Code_Page_Mismatched ;AN000;;FT. code page mismatch + JNZ NORERR ;AN000;;FT. no + transfer From_GetSet ;AN000;;FT. yes +NORERR: ;AN000; + +;; File Tagging DOS 4.00 + transfer Sys_Ret_Err ; no free, return error + +EndProc $Open + +BREAK <$Creat - create a brand-new file> + +; +; $Creat - create the directory entry specified in DS:DX and give it the +; initial attributes contained in CX +; Inputs: DS:DX - ASCIZ path name +; CX - initial attributes +; Outputs: Carry set - AX has error code +; Carry reset - AX has handle +; Registers modified: all + +Procedure $Creat,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup + fmt TypSysCall,LevLog,<"Create\n"> + fmt TypSysCall,LevArgs,<" Att = $x file = '$S'\n">, +IF DBCS ;AN000; + MOV [Temp_Var],CX ;AN000;KK. set variable with attribute ;AN000; +ENDIF ;AN000; + SaveReg ; Save attributes on stack + MOV CX,OFFSET DOSGroup:DOS_Create; routine to call +AccessSet: + mov SAttrib,attr_hidden+attr_system + JMP AccessFile ; use good ol' open +EndProc $Creat + +BREAK <$CHMOD - change file attributes> +; +; Assembler usage: +; LDS DX, name +; MOV CX, attributes +; MOV AL,func (0=get, 1=set) +; INT 21h +; Error returns: +; AX = error_path_not_found +; AX = error_access_denied +; + + procedure $CHMOD,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup + MOV DI,OFFSET DOSGroup:OpenBuf ; appropriate buffer + SaveReg ; save function and attributes + MOV SI,DX ; get things in appropriate places + invoke TransPathSet ; get correct path + RestoreReg ; and get function and attrs back + JC ChModErr ; errors get mapped to path not found + Context DS ; set up for later possible calls + CMP cMeta,-1 + JNZ ChModErr + MOV [SAttrib],attr_hidden+attr_system+attr_directory + SUB AL,1 ; fast way to discriminate + JB ChModGet ; 0 -> go get value + JZ ChModSet ; 1 -> go set value + MOV EXTERR_LOCUS,errLoc_Unk ; Extended Error Locus + error error_invalid_function ; bad value +ChModGet: + invoke Get_File_Info ; suck out the ol' info + JC ChModE ; error codes are already set for ret + invoke Get_User_stack ; point to user saved vaiables + MOV [SI.User_CX],AX ; return the attributes + transfer Sys_Ret_OK ; say sayonara +ChModSet: + MOV AX,CX ; get attrs in position + invoke Set_File_Attribute ; go set + JC ChModE ; errors are set + transfer Sys_Ret_OK +ChModErr: + mov al,error_path_not_found +ChmodE: + Transfer SYS_RET_ERR +EndProc $ChMod + +BREAK <$UNLINK - delete a file entry> +; +; Assembler usage: +; LDS DX, name +; IF VIA SERVER DOS CALL +; MOV CX,SEARCH_ATTRIB +; MOV AH, Unlink +; INT 21h +; +; Error returns: +; AX = error_file_not_found +; = error_access_denied +; + + procedure $UNLINK,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup + SaveReg ; Save possible CX input parm + MOV SI,DX ; Point at input string + MOV DI,OFFSET DOSGroup:OpenBuf ; temp spot for path + invoke TransPathSet ; go get normalized path + RestoreReg + JC ChModErr ; badly formed path + CMP cMeta,-1 ; meta chars? + JNZ NotFound + Context DS + mov ch,attr_hidden+attr_system ; unlink appropriate files + call SetAttrib + invoke DOS_Delete ; remove that file + JC UnlinkE ; error is there + + + transfer Sys_Ret_OK ; okey doksy +NotFound: + MOV AL,error_path_not_found +UnlinkE: + transfer Sys_Ret_Err ; bye +EndProc $UnLink + +BREAK <$RENAME - move directory entries around> +; +; Assembler usage: +; LDS DX, source +; LES DI, dest +; IF VIA SERVER DOS CALL +; MOV CX,SEARCH_ATTRIB +; MOV AH, Rename +; INT 21h +; +; Error returns: +; AX = error_file_not_found +; = error_not_same_device +; = error_access_denied + + procedure $RENAME,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup + SaveReg ; save source and possible CX arg + PUSH ES + POP DS ; move dest to source + MOV SI,DI ; save for offsets + MOV DI,OFFSET DOSGroup:RenBuf + + MOV WORD PTR [NO_FILTER_DPATH],SI ;AN000;;IFS. save them for IFS + MOV WORD PTR [NO_FILTER_DPATH+2],DS ;AN000;;IFS. + + invoke TransPathSet ; munge the paths + PUSH WFP_Start ; get pointer + POP Ren_WFP ; stash it + RestoreReg ; get back source and possible CX arg +epjc2: JC ChModErr ; get old error + CMP cMeta,-1 + JNZ NotFound + SaveReg ; Save possible CX arg + MOV DI,OFFSET DOSGroup:OpenBuf ; appropriate buffer + invoke TransPathSet ; wham + RestoreReg + JC EPJC2 + Context DS + CMP cMeta,-1 + JB NotFound + + PUSH WORD PTR [THISCDS] ;AN000;;MS.save thiscds + PUSH WORD PTR [THISCDS+2] ;AN000;;MS. + MOV DI,OFFSET DOSGROUP:OpenBuf ;AN000;;MS. + PUSH SS ;AN000;;MS. + POP ES ;AN000;;MS.es:di-> source + XOR AL,AL ;AN000;;MS.scan all CDS +rnloop: ;AN000; + invoke GetCDSFromDrv ;AN000;;MS. + JC dorn ;AN000;;MS. end of CDS + invoke StrCmp ;AN000;;MS. current dir ? + JZ rnerr ;AN000;;MS. yes + INC AL ;AN000;;MS. next + JMP rnloop ;AN000;;MS. +rnerr: ;AN000; + ADD SP,4 ;AN000;;MS. pop thiscds + error error_current_directory ;AN000;;MS. +dorn: ;AN000; + POP WORD PTR SS:[THISCDS+2] ;AN000;;MS. + POP WORD PTR SS:[THISCDS] ;AN000;;MS. + Context DS + mov ch,attr_directory+attr_hidden+attr_system; rename appropriate files + call SetAttrib + invoke DOS_Rename ; do the deed + JC UnlinkE ; errors + + + transfer Sys_Ret_OK +EndProc $Rename + +Break <$CreateNewFile - Create a new directory entry> + +; +; CreateNew - Create a new directory entry. Return a file handle if there +; was no previous directory entry, and fail if a directory entry with +; the same name existed previously. +; +; Inputs: DS:DX point to an ASCIZ file name +; CX contains default file attributes +; Outputs: Carry Clear: +; AX has file handle opened for read/write +; Carry Set: +; AX has error code +; Registers modified: All + + Procedure $CreateNewFile,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup + fmt TypSysCall,LevLog,<"CreateNew\n"> + fmt TypSysCall,LevArgs,<" Att = $x file = '$S'\n">, +IF DBCS ;AN000; + MOV [Temp_Var],CX ;AN000;KK. set variable with attribute +ENDIF ;AN000; + SaveReg ; Save attributes on stack + MOV CX,OFFSET DOSGroup:DOS_Create_New ; routine to call + JMP AccessSet ; use good ol' open +EndProc $CreateNewFile + +Break + +; +; HexToAsciz - used to convert register into a hex number. +; +; Inputs: AX contains the number +; ES:DI point to destination +; Outputs: ES:DI updated +; Registers modified: DI,CX + +Procedure HexToAsciz,NEAR + mov cx,4 ; 4 digits in AX +GetDigit: + SaveReg ; preserve count + mov cl,4 + ROL AX,CL ; move leftmost nibble into rightmost + SaveReg ; preserve remainder of digits + AND AL,0Fh ; grab low nibble + ADD AL,'0' ; turn into digit + CMP AL,'9' ; bigger than 9 + JBE DoStore ; no, stash it + ADD AL,'A'-'0'-10 ; convert into uppercase letter +DoStore: + STOSB ; drop in the character + RestoreReg ; regain the number and count + loop GetDigit ; while there's more digits, go do 'em + return +EndProc HexToAsciz + +Break <$CreateTempFile - create a unique name> + +; +; $CreateTemp - given a directory, create a unique name in that directory. +; Method used is to get the current time, convert to a name and attempt +; a create new. Repeat until create new succeeds. +; +; Inputs: DS:DX point to a null terminated directory name. +; CX contains default attributes +; Outputs: Unique name is appended to DS:DX directory. +; AX has handle +; Registers modified: all + + Procedure $CreateTempFile,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup + fmt TypSysCall,LevLog,<"CreateTmp\n"> + fmt TypSysCall,LevArgs,<" Att = $x dir = '$S'\n">, +PUBLIC FILE001S,FILE001E +FILE001S: + LocalVar EndPtr,DWORD + LocalVar FilPtr,DWORD + LocalVar Attr,WORD +FILE001E: + Enter + TEST CX,NOT attr_changeable + JZ OKatts ; Ok if no non-changeable bits set +; +; We need this "hook" here to detect these cases (like user sets one both of +; vol_id and dir bits) because of the structure of the or $CreateNewFile loop +; below. The code loops on error_access_denied, but if one of the non +; changeable attributes is specified, the loop COULD be infinite or WILL be +; infinite because CreateNewFile will fail with access_denied always. Thus we +; need to detect these cases before getting to the loop. +; + MOV AX,error_access_denied + JMP SHORT SETTMPERR + +OKatts: + MOV attr,CX ; save attribute + MOV FilPtrL,DX ; pointer to file + MOV FilPtrH,DS + MOV EndPtrH,DS ; seg pointer to end of dir + PUSH DS + POP ES ; destination for nul search + MOV DI,DX + MOV CX,DI + NEG CX ; number of bytes remaining in segment + IF DBCS ;AN000; +Kloop: ;AN000;; 2/13/KK + MOV AL, BYTE PTR ES:[DI] ;AN000;; 2/13/KK + INC DI ;AN000;; 2/13/KK + OR AL,AL ;AN000;; 2/13/KK + JZ GOTEND ;AN000;; 2/13/KK + invoke testkanj ;AN000;; 2/13/KK + jz Kloop ;AN000;; 2/13/KK + inc di ;AN000;; Skip over second kanji byte 2/13/KK + CMP BYTE PTR ES:[DI],0 ;AN000;; 2/13/KK + JZ STOREPTH ;AN000; When char before NUL is sec Kanji byte + ;AN000; do not look for path char. 2/13/KK + jmp Kloop ;AN000; 2/13/KK +GOTEND: ;AN000; 2/13/KK + ELSE ;AN000; + OR CX,CX ;AN000;MS. cx=0 ? ds:dx on segment boundary + JNZ okok ;AN000;MS. no + MOV CX,-1 ;AN000;MS. +okok: ;AN000; + XOR AX,AX ;AN000; + REPNZ SCASB ;AN000; + ENDIF ;AN000; + DEC DI ; point back to the null + MOV AL,ES:[DI-1] ; Get char before the NUL + invoke PathChrCmp ; Is it a path separator? + JZ SETENDPTR ; Yes +STOREPTH: + MOV AL,'\' + STOSB ; Add a path separator (and INC DI) +SETENDPTR: + MOV EndPtrL,DI ; pointer to the tail +CreateLoop: + Context DS ; let ReadTime see variables + SaveReg + invoke ReadTime ; go get time + RestoreReg +; +; Time is in CX:DX. Go drop it into the string. +; + les di,EndPtr ; point to the string + mov ax,cx + call HexToAsciz ; store upper word + mov ax,dx + call HexToAsciz ; store lower word + xor al,al + STOSB ; nul terminate + LDS DX,FilPtr ; get name +ASSUME DS:NOTHING + MOV CX,Attr ; get attr + SaveReg + CALL $CreateNewFile ; try to create a new file + RestoreReg + JNC CreateDone ; failed, go try again +; +; The operation failed and the error has been mapped in AX. Grab the extended +; error and figure out what to do. +; + mov ax,ExtErr + cmp al,error_file_exists + jz CreateLoop ; file existed => try with new name + cmp al,error_access_denied + jz CreateLoop ; access denied (attr mismatch) + +; CMP AL,error_file_exists ; certain errors cause failure +; JZ CreateLoop +; CMP AL,error_access_denied +; JNZ SETTMPERR ; Error out +; CMP [EXTERR],error_cannot_make ; See if it's REALLY an att mismatch +; JNZ CreateLoop ; It was, try again +; MOV AL,error_cannot_make ; Return this "extended" error + +SETTMPERR: + STC +CreateDone: + Leave + JC CreateFail + transfer Sys_Ret_OK ; success! +CreateFail: + transfer Sys_Ret_Err +EndProc $CreateTempFile + +Break + +; +; SetAttrib will set the search attribute (SAttrib) either to the normal +; (CH) or to the value in CL if the current system call is through +; serverdoscall. +; +; Inputs: fSharing == FALSE => set sattrib to CH +; fSharing == TRUE => set sattrib to CL +; Outputs: none +; Registers changed: CX + +procedure SetAttrib,NEAR + assume ds:nothing,es:nothing + test fSharing,-1 + jnz Set + mov cl,ch +Set: + mov SAttrib,cl + return +EndProc SetAttrib + + +Break + +; Input: AL= 0 reserved AH=6CH +; BX= mode +; CL= create attribute CH=search attribute (from server) +; DX= flag +; DS:SI = file name +; ES:DI = parm list +; DD SET EA list (-1) null +; DW n parameters +; DB type (TTTTTTLL) +; DW IOMODE +; Function: Extended Open +; Output: carry clear +; AX= handle +; CX=1 file opened +; 2 file created/opened +; 3 file replaced/opened +; carry set: AX has error code +; + + +procedure $Extended_Open,NEAR ;AN000; + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP ;AN000; + + MOV [XA_from],0 ;AN000;EO. init for set XA + MOV [EXTOPEN_FLAG],DX ;AN000;EO. save ext. open flag + MOV [EXTOPEN_IO_MODE],0 ;AN000;EO. initialize IO mode + TEST DX,reserved_bits_mask ;AN000;EO. reserved bits 0 ? + JNZ ext_inval2 ;AN000;EO. no + MOV AH,DL ;AN000;EO. make sure flag is right + CMP DL,0 ;AN000;EO. all fail ? + JZ ext_inval2 ;AN000;EO. yes, error + AND DL,exists_mask ;AN000;EO. get exists action byte + CMP DL,2 ;AN000;EO, > 02 + JA ext_inval2 ;AN000;EO. yes ,error + AND AH,not_exists_mask ;AN000;EO. get no exists action byte + CMP AH,10H ;AN000;EO. > 10 + JA ext_inval2 ;AN000;EO. yes error + +; CMP DI,-1 ;AN000;EO. null parm list +; JZ no_parm ;AN000;EO. yes +; ;AN000;EO +; PUSH CX ;AN000;EO. +; ;AN000;EO. +; MOV CX,ES:[DI.EXT_NUM_OF_PARM];AN000;EO. get number of parms +; OR CX,CX ;AN000;EO. 0 pamrs ? +; JZ parmend ;AN000;EO. yes +; PUSH SI ;AN000;EO. +; PUSH DS ;AN000;EO. +; MOV SI,DI ;AN000;EO. +; ADD SI,size EXT_OPEN_PARM ;AN000;EO. position to 1st parm +; PUSH ES ;AN000;EO. +; POP DS ;AN000;EO. ds:si -> parm list +; CALL GetIOParms ;AN000;EO. +; POP DS ;AN000;EO. +; POP SI ;AN000;EO. +;parmend: ;AN000;EO +; POP CX ;AN000;EO. restore CX +;no_parm: ;AN000;EO. + MOV [SAVE_ES],ES ;AN000;EO. save API parms + MOV [SAVE_DI],DI ;AN000;EO. + PUSH [EXTOPEN_FLAG] ;AN000;EO. + POP [SAVE_DX] ;AN000;EO. + MOV [SAVE_CX],CX ;AN000;EO. + MOV [SAVE_BX],BX ;AN000;EO. + MOV [SAVE_DS],DS ;AN000;EO. + MOV [SAVE_SI],SI ;AN000;EO. + MOV DX,SI ;AN000;EO. ds:dx points to file name + MOV AX,BX ;AN000;EO. ax= mode + +; TEST [EXTOPEN_FLAG],no_code_page_check ;AN000;EO. check no code page +; JNZ no_cdpg_chk ;AN000;;EO. no + JMP SHORT goopen2 ;AN000;;EO. do nromal +ext_inval2: ;AN000;;EO. + error error_Invalid_Function ;AN000;EO.. invalid function +ext_inval_parm: ;AN000;EO.. + POP CX ;AN000;EO.. pop up satck + POP SI ;AN000;EO.. + error error_Invalid_data ;AN000;EO.. invalid parms +error_return: ;AN000;EO. + ret ;AN000;EO.. return with error +;no_cdpg_chk: EO. +; MOV [CPSWFLAG],0 ;AN000;EO.. set CPSW flag off +goopen2: ;AN000; + TEST BX,int_24_error ;AN000;EO.. disable INT 24 error ? + JZ goopen ;AN000;EO.. no + OR [EXTOPEN_ON],EXT_OPEN_I24_OFF ;AN000;EO.. set bit to disable + +goopen: ;AN000; + OR [EXTOPEN_ON],EXT_OPEN_ON ;AN000;EO.. set Extended Open active + AND [EXTOPEN_FLAG],0FFH ;AN000;EO.create new ? + CMP [EXTOPEN_FLAG],ext_exists_fail + ext_nexists_create ;AN000;FT. + JNZ chknext ;AN000;;EO. no + invoke $CreateNewFile ;AN000;;EO. yes + JC error_return ;AN000;;EO. error + CMP [EXTOPEN_ON],0 ;AN000;;EO. IFS does it + JZ ok_return2 ;AN000;;EO. yes + MOV [EXTOPEN_FLAG],action_created_opened ;AN000;EO. creted/opened + MOV [XA_from],By_Create ;AN000;;EO. for set xa + JMP setXAttr ;AN000;;EO. set XAs +ok_return2: + transfer SYS_RET_OK ;AN000;;EO. +chknext: + TEST [EXTOPEN_FLAG],ext_exists_open ;AN000;;EO. exists open + JNZ exist_open ;AN000;;EO. yes + invoke $Creat ;AN000;;EO. must be replace open + JC error_return ;AN000;;EO. return with error + CMP [EXTOPEN_ON],0 ;AN000;;EO. IFS does it + JZ ok_return2 ;AN000;;EO. yes + MOV [EXTOPEN_FLAG],action_created_opened ;AN000;EO. prsume create/open + MOV [XA_from],By_Create ;AN000;EO. for set xa + TEST [EXTOPEN_ON],ext_file_not_exists ;AN000;;EO. file not exists ? + JNZ setXAttr ;AN000;;EO. no + MOV [EXTOPEN_FLAG],action_replaced_opened ;AN000;;EO. replaced/opened + MOV [XA_from],0 ;AN000;EO. for set xa + JMP SHORT setXAttr ;AN000;;EO. set XAs +error_return2: + ret ;AN000;;EO. return with error + ;AN000; +exist_open: ;AN000; + test fSharing,-1 ;AN000;;EO. server doscall? + jz noserver ;AN000;;EO. no + MOV CL,CH ;AN000;;EO. cl=search attribute + +noserver: + invoke $Open2 ;AN000;;EO. do open + JNC ext_ok ;AN000;;EO. + CMP [EXTOPEN_ON],0 ;AN000;;EO. error and IFS call + JZ error_return2 ;AN000;;EO. return with error +local_extopen: + + CMP AX,error_file_not_found ;AN000;;EO. file not found error + JNZ error_return2 ;AN000;;EO. no, + TEST [EXTOPEN_FLAG],ext_nexists_create;AN000;;EO. want to fail + JNZ do_creat ;AN000;;EO. yes + JMP extexit ;AN000;;EO. yes +do_creat: + MOV [XA_from],By_Create ;AN000;;EO. for set xa + MOV CX,[SAVE_CX] ;AN000;;EO. get ds:dx for file name + LDS SI,DWORD PTR [SAVE_SI] ;AN000;;EO. cx = attribute + MOV DX,SI ;AN000;;EO. + invoke $Creat ;AN000;;EO. do create + JC extexit ;AN000;;EO. error + MOV [EXTOPEN_FLAG],action_created_opened ;AN000;;EO. is created/opened + JMP SHORT setXAttr ;AN000;;EO. set XAs + +ext_ok: + CMP [EXTOPEN_ON],0 ;AN000;;EO. IFS call ? + JZ ok_return ;AN000;;EO. yes + MOV [EXTOPEN_FLAG],action_opened ;AN000;;EO. opened +setXAttr: +; LES DI,DWORD PTR [SAVE_DI] ;AN000;EO. + PUSH AX ;AN000;;EO. save handle for final +; MOV BX,AX ;AN000;;EO. bx= handle +; MOV AX,04H ;AN000;;EO. set extended attr by handle +; PUSH DS ;AN000;;EO. save file name addr +; PUSH DX ;AN000;;EO. +; CMP DI,-1 ;AN000;;EO. null parm list +; JZ nosetea ;AN000;;EO. yes +; CMP WORD PTR ES:[DI],-1 ;AN000;;EO. null set list +; JZ nosetea ;AN000;;EO. yes +; LES DI,DWORD PTR ES:[DI] ;AN000;;EO. es:di -> set list +; invoke $File_times ;AN000;;EO. +;nosetea: ;AN000; EO +; POP DX ;AN000;;EO. restore file name addr +; POP DS ;AN000;;EO. +; JC extexit2 ;AN000;;EO. + invoke get_user_stack ;AN000;;EO. + MOV AX,[EXTOPEN_FLAG] ;AN000;;EO. + MOV [SI.USER_CX],AX ;AN000;;EO. set action code for cx + POP AX ;AN000;;EO. + MOV [SI.USER_AX],AX ;AN000;;EO. set handle for ax + +ok_return: ;AN000; + transfer SYS_RET_OK ;AN000;;EO. + +extexit2: ;AN000; ERROR RECOVERY + + POP BX ;AN000;EO. close the handle + PUSH AX ;AN000;EO. save error code from set XA + CMP [EXTOPEN_FLAG],action_created_opened ;AN000;EO. from create + JNZ justopen ;AN000;EO. + LDS SI,DWORD PTR [SAVE_SI] ;AN000;EO. cx = attribute + LDS DX,DWORD PTR [SI] ;AN000;EO. + invoke $UNLINK ;AN000;EO. delete the file + JMP SHORT reserror ;AN000;EO. + +justopen: ;AN000; + invoke $close ;AN000;EO. pretend never happend +reserror: ;AN000; + POP AX ;AN000;EO. retore error code from set XA + JMP SHORT extexit ;AN000;EO. + + +ext_file_unfound: ;AN000; + MOV AX,error_file_not_found ;AN000;EO. + JMP SHORT extexit ;AN000;EO. +ext_inval: ;AN000; + MOV AX,error_invalid_function;AN000;EO. +extexit: + transfer SYS_RET_ERR ;AN000;EO. + +EndProc $Extended_Open ;AN000; + + +Break + +; +; +; Inputs: DS:SI -> IO parm list +; CX= number of parms +; Function: get IO parms from parm list +; Outputs: [EXT_IOMODE]= IO mode parm + +;procedure GetIOParms,NEAR +; assume ds:nothing,es:nothing +; +; LODSB ; get parm type ;AN000; +; CMP AL,0*100B+10B ; have IOMODE ;AN000; +; JE SET_IOMODE ;AN000; +; AND AL,00000011B ; decode it ;AN000; +; JZ SKIP_ASCIIZ ;AN000; +; DEC AL ;AN000; +; JZ SKIP_LEN ;AN000; +;; DEC AL ;AN000; +; JZ SKIP_WORD ;AN000; +;SKIP_DWORD: ; copy DWORD parm ;AN000; +; LODSW ;AN000; +;SKIP_WORD: ; copy WORD parm ;AN000; +; LODSW ;AN000; +; JMP SHORT NEXT_PARM ;AN000; +;SET_IOMODE: ; copy IOMODE ;AN000; +; LODSW ;AN000; +; MOV [EXTOPEN_IO_MODE],AX ;AN000; +; JMP SHORT NEXT_PARM ;AN000; +;SKIP_LEN: ; copy LENGTH parm ;AN000; +; LODSW ;AN000; +; ADD SI,AX ;AN000; +; JMP SHORT NEXT_PARM ;AN000; +;SKIP_ASCIIZ: ; copy ASCIIZ parm ;AN000; +; LODSB ;AN000; +; OR AL,AL ;AN000; +; JNE SKIP_ASCIIZ ;AN000; +;NEXT_PARM: ;AN000; +; LOOP GetIOParms ;AN000; +; return ;AN000; +;EndProc GetIOParms ;AN000; + + +CODE ENDS +END + \ No newline at end of file diff --git a/v4.0/src/DOS/FINFO.ASM b/v4.0/src/DOS/FINFO.ASM new file mode 100644 index 0000000..0df2bc1 --- /dev/null +++ b/v4.0/src/DOS/FINFO.ASM @@ -0,0 +1,286 @@ +; SCCSID = @(#)finfo.asm 1.1 85/04/11 +TITLE FILE_INFO - Internal Get/Set File Info routines +NAME FILE_INFO +; Low level routines for returning file information and setting file +; attributes +; +; GET_FILE_INFO +; SET_FILE_ATTRIBUTE +; +; Modification history: +; +; Created: ARR 30 March 1983 +; + +; +; get the appropriate segment definitions +; +.xlist +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +include fastxxxx.inc +include fastopen.inc +.cref +.list + +Installed = TRUE + + i_need THISCDS,DWORD + i_need CURBUF,DWORD + i_need NoSetDir,BYTE + i_need THISDRV,BYTE + I_need EXTERR_CLASS,BYTE + I_need EXTERR_ACTION set + I_need EXTERR_LOCUS,BYTE + i_need DMAADD,DWORD + i_need FastOpenFlg,BYTE + +SUBTTL GET_FILE_INFO -- Get File Information +PAGE + +; Inputs: +; [WFP_START] Points to WFP string ("d:/" must be first 3 chars, NUL +; terminated) +; [CURR_DIR_END] Points to end of Current dir part of string +; ( = -1 if current dir not involved, else +; Points to first char after last "/" of current dir part) +; [THISCDS] Points to CDS being used +; (Low word = -1 if NUL CDS (Net direct request)) +; [SATTRIB] Is attribute of search, determines what files can be found +; Function: +; Get Information about a file +; Returns: +; CARRY CLEAR +; AX = Attribute of file +; CX = Time stamp of file +; DX = Date stamp of file +; BX:DI = Size of file (32 bit) +; CARRY SET +; AX is error code +; error_file_not_found +; Last element of path not found +; error_path_not_found +; Bad path (not in curr dir part if present) +; error_bad_curr_dir +; Bad path in current directory part of path +; DS preserved, others destroyed + + procedure GET_FILE_INFO,NEAR + DOSAssume CS,,"Get_File_Info" + ASSUME ES:NOTHING + + Invoke TestNet + JNC Local_Info +; invoke OWN_SHARE2 ;IFS. IFS owns share ? ;AN000; +; JZ ifsshare ;IFS. yes ;AN000; +; PUSH WORD PTR [DMAADD+2] ;IFS. save DMAADD ;AN000; +; PUSH WORD PTR [DMAADD] ;IFS. ;AN000; +; invoke IFS_SEARCH_FIRST ;IFS. do search first ;AN000; +; JC nofiles ;IFS. file not existing ;AN000; +delete_next_file: ;IFS. ;AN000; +; invoke IFS_REN_DEL_CHECK ;IFS. do REN_DEL_CHECK ;AN000; +; JNC share_okok ;IFS. share ok ;AN000; +; MOV AX,error_sharing_violation ;IFS. share violation ;AN000; +; JMP SHORT nofiles ;IFS. ;AN000; +share_okok: +; POP WORD PTR [DMAADD] ;IFS. retor DMAADD ;AN000; +; POP WORD PTR [DMAADD+2] ;IFS. ;AN000; +ifsshare: +IF NOT Installed + transfer NET_GET_FILE_INFO +ELSE + MOV AX,(multNET SHL 8) OR 15 + INT 2FH + return +ENDIF +nofiles: +; POP WORD PTR [DMAADD] ;IFS. retor DMAADD ;AN000; +; POP WORD PTR [DMAADD+2] ;IFS. ;AN000; +; ret ;IFS. return + +LOCAL_INFO: + EnterCrit critDisk + MOV [NoSetDir],1 ; if we find a dir, don't change to it + invoke Get_FAST_PATH +info_check: + JNC info_check_dev + +NO_PATH: + DOSAssume CS,,"FINFO/No_Path" + ASSUME ES:NOTHING + + JNZ bad_path + OR CL,CL + JZ bad_path +info_no_file: + MOV AX,error_file_not_found +BadRet: + STC +justRet: + LeaveCrit critDisk + return + +bad_path: + MOV AX,error_path_not_found + jmp BadRet + +info_check_dev: + OR AH,AH + JS info_no_file ; device + PUSH DS + MOV DS,WORD PTR [CURBUF+2] +ASSUME DS:NOTHING + MOV SI,BX + XOR BX,BX ; Assume size=0 (dir) + MOV DI,BX + MOV CX,[SI.dir_time] + MOV DX,[SI.dir_date] + XOR AH,AH + MOV AL,[SI.dir_attr] + TEST AL,attr_directory + JNZ NO_SIZE + MOV DI,[SI.dir_size_l] + MOV BX,[SI.dir_size_h] +NO_SIZE: + POP DS + CLC + jmp JustRet +EndProc GET_FILE_INFO + +Break + +; Inputs: +; [WFP_START] Points to WFP string ("d:/" must be first 3 chars, NUL +; terminated) +; [CURR_DIR_END] Points to end of Current dir part of string +; ( = -1 if current dir not involved, else +; Points to first char after last "/" of current dir part) +; [THISCDS] Points to CDS being used +; (Low word = -1 if NUL CDS (Net direct request)) +; [SATTRIB] is attribute of search (determines what files may be found) +; AX is new attributes to give to file +; Function: +; Set File Attributes +; Returns: +; CARRY CLEAR +; No error +; CARRY SET +; AX is error code +; error_file_not_found +; Last element of path not found +; error_path_not_found +; Bad path (not in curr dir part if present) +; error_bad_curr_dir +; Bad path in current directory part of path +; error_access_denied +; Attempt to set an attribute which cannot be set +; (attr_directory, attr_volume_ID) +; error_sharing_violation +; Sharing mode of file did not allow the change +; (this request requires exclusive write/read access) +; (INT 24H generated) +; DS preserved, others destroyed + + procedure SET_FILE_ATTRIBUTE,NEAR + DOSAssume CS,,"Set_File_Attribute" + ASSUME ES:NOTHING + + TEST AX,NOT attr_changeable + JZ set_look +BAD_ACC: + MOV ExtErr_Locus,errLoc_UNK + MOV ExtErr_Class,errClass_Apperr + MOV ExtErr_Action,errAct_Abort + MOV AX,error_access_denied + STC + return + +set_look: + Invoke TestNet + JNC Local_Set + +IF NOT Installed + transfer NET_SEQ_SET_FILE_ATTRIBUTE +ELSE + PUSH AX + MOV AX,(multNET SHL 8) OR 14 + INT 2FH + POP BX ; clean stack + return +ENDIF + +LOCAL_SET: + EnterCrit critDisk + PUSH AX ; Save new attributes + MOV [NoSetDir],1 ; if we find a dir, don't change to it + invoke GetPath ; get path through fastopen if there ;AC000; + JNC set_check_device + POP BX ; Clean stack (don't zap AX) + JMP NO_PATH + +set_check_device: + OR AH,AH + JNS set_check_share + POP AX + LeaveCrit critDisk + JMP BAD_ACC ; device + +set_check_share: + POP AX ; Get new attributes + invoke REN_DEL_Check + JNC set_do + MOV AX,error_sharing_violation + jmp short ok_bye + +set_do: + LES DI,[CURBUF] + AND BYTE PTR ES:[BX].dir_attr,NOT attr_changeable + OR BYTE PTR ES:[BX].dir_attr,AL + + TEST ES:[DI.buf_flags],buf_dirty ;LB. if already dirty ;AN000; + JNZ yesdirty ;LB. don't increment dirty count ;AN000; + invoke INC_DIRTY_COUNT ;LB. ;AN000; + OR ES:[DI.buf_flags],buf_dirty +yesdirty: + MOV AL,[THISDRV] +;;;; 10/1/86 F.C update fastopen cache + PUSH DX + PUSH DI + MOV AH,0 ; dir entry update + MOV DL,AL ; drive number A=0,B=1,, + MOV DI,BX ; ES:DI -> dir entry + invoke FastOpen_Update + POP DI + POP DX +;;;; 9/11/86 F.C update fastopen cache + invoke FlushBuf + JNC OK_BYE + MOV AX,error_file_not_found +OK_BYE: + LeaveCrit critDisk + return + +EndProc SET_FILE_ATTRIBUTE + + + + procedure GET_FAST_PATH,NEAR + ASSUME DS:NOTHING,ES:NOTHING + + OR [FastOpenFlg],FastOpen_Set ;FO. trigger fastopen ;AN000; + invoke GetPath + PUSHF ;FO. ;AN000; + AND [FastOpenFlg],Fast_yes ;FO. clear all fastopen flags ;AN000; + POPF ;FO. ;AN000; + return + +EndProc GET_FAST_PATH + +CODE ENDS + END diff --git a/v4.0/src/DOS/GETSET.ASM b/v4.0/src/DOS/GETSET.ASM new file mode 100644 index 0000000..70c8cd3 --- /dev/null +++ b/v4.0/src/DOS/GETSET.ASM @@ -0,0 +1,912 @@ +; SCCSID = @(#)getset.asm 1.2 85/07/23 +TITLE GETSET - GETting and SETting MS-DOS system calls +NAME GETSET +; +; System Calls which get and set various things +; +; $GET_VERSION +; $GET_VERIFY_ON_WRITE +; $SET_VERIFY_ON_WRITE +; $INTERNATIONAL +; $GET_DRIVE_FREESPACE +; $GET_DMA +; $SET_DMA +; $GET_DEFAULT_DRIVE +; $SET_DEFAULT_DRIVE +; $GET_INTERRUPT_VECTOR +; $SET_INTERRUPT_VECTOR +; RECSET +; $CHAR_OPER +; $GetExtendedError DOS 3.3 +; Get_Global_CdPg DOS 4.0 +; $ECS_CALL DOS 4.0 +; +; Revision history: +; +; Created: ARR 30 March 1983 +; +; A000 version 4.0 Jan. 1988 +; A006 D503-- fake version for IBMCACHE +; A008 P4070- faske version for MS WINDOWS + +.xlist +; +; get the appropriate segment definitions +; +include dosseg.asm + +IFNDEF ALTVECT +ALTVECT EQU 0 ; FALSE +ENDIF + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +include dossym.inc +include devsym.inc +include doscntry.inc +.cref +.list + + i_need USERNUM,WORD + i_need MSVERS,WORD + i_need VERFLG,BYTE + i_need CNTCFLAG,BYTE + i_need DMAADD,DWORD + i_need CURDRV,BYTE + i_need chSwitch,BYTE + i_need COUNTRY_CDPG,byte ;DOS 3.3 + I_need CDSCount,BYTE + I_need ThisCDS,DWORD + i_need EXTERR,WORD + i_need EXTERR_ACTION,BYTE + i_need EXTERR_CLASS,BYTE + i_need EXTERR_LOCUS,BYTE + i_need EXTERRPT,DWORD + i_need UCASE_TAB,BYTE + i_need FILE_UCASE_TAB,BYTE + i_need InterCon,BYTE + i_need CURRENTPDB,WORD + i_need DBCS_TAB,BYTE ;AN000; + i_need Special_version,WORD ;AN006; + i_need Fake_Count,BYTE ;AN008; + i_need NLS_YES,BYTE ;AN000; + i_need NLS_yes2,BYTE ;AN000; + i_need NLS_NO,BYTE ;AN000; + i_need NLS_no2,BYTE ;AN000; + + +BREAK <$Get_Version -- Return DOS version number> + procedure $GET_VERSION,NEAR +ASSUME DS:NOTHING,ES:NOTHING + +; Inputs: +; None +; Function: +; Return DOS version number +; Outputs: +; OEM number in BH +; User number in BL:CX (24 bits) +; Version number as AL.AH in binary +; NOTE: On pre 1.28 DOSs AL will be zero + + context DS + MOV BX,[USERNUM + 2] + MOV CX,[USERNUM] + MOV AX,[MSVERS] + invoke get_user_stack +ASSUME DS:NOTHING + MOV [SI.user_BX],BX + MOV [SI.user_CX],CX + CMP CS:[Fake_Count],0FFH ;AN008; + JZ reg ;AN008; + CMP CS:[Fake_Count],0 ;AN008; + JZ usual ;AN008; + DEC CS:[Fake_Count] ;AN008; +reg: ;AN008; + CMP CS:[Special_version],0 ;AN006; + JZ usual ;AN006; + MOV AX,CS:[Special_version] ;AN006; +usual: ;AN006; + MOV [SI.user_AX],AX ; Really only sets AH + return +EndProc $GET_VERSION + +BREAK <$Get_Verify_on_Write - return verify-after-write flag> + procedure $GET_VERIFY_ON_WRITE,NEAR +ASSUME DS:NOTHING,ES:NOTHING + +; Inputs: +; none. +; Function: +; returns flag +; Returns: +; AL = value of VERIFY flag + + MOV AL,[VERFLG] + return +EndProc $GET_VERIFY_ON_WRITE + +BREAK <$Set_Verify_on_Write - Toggle verify-after-write flag> + procedure $SET_VERIFY_ON_WRITE,NEAR +ASSUME DS:NOTHING,ES:NOTHING + +; Inputs: +; AL = desired value of VERIFY flag +; Function: +; Sets flag +; Returns: +; None + + AND AL,1 + MOV [VERFLG],AL + return +EndProc $SET_VERIFY_ON_WRITE + +BREAK <$International - return country-dependent information> +; +; Inputs: +; MOV AH,International +; MOV AL,country (al = 0 => current country) +; [MOV BX,country] +; LDS DX,block +; INT 21 +; Function: +; give users an idea of what country the application is running +; Outputs: +; IF DX != -1 on input (get country) +; AL = 0 means return current country table. +; 0 internat_block_max, +; in the correct order for being returned by the +; INTERNATIONAL call as follows: +; WORD Date format 0=mdy, 1=dmy, 2=ymd +; 5 BYTE Currency symbol null terminated +; 2 BYTE thousands separator null terminated +; 2 BYTE Decimal point null terminated +; 2 BYTE Date separator null terminated +; 2 BYTE Time separator null terminated +; 1 BYTE Bit field. Currency format. +; Bit 0. =0 $ before # =1 $ after # +; Bit 1. no. of spaces between # and $ (0 or 1) +; 1 BYTE No. of significant decimal digits in currency +; 1 BYTE Bit field. Time format. +; Bit 0. =0 12 hour clock =1 24 hour +; DWORD Call address of case conversion routine +; 2 BYTE Data list separator null terminated. +; Carry: +; Register AX has the error code. +; IF DX = -1 on input (set current country) +; AL = 0 is an error +; 0 +; +; Inputs: +; if AL >= 20H +; AL= 20H capitalize single char, DL= char +; 21H capitalize string ,CX= string length +; 22H capitalize ASCIIZ string +; 23H YES/NO check, DL=1st char DH= 2nd char (DBCS) +; 80H bit 0 = use normal upper case table +; 1 = use file upper case table +; DS:DX points to string +; +; else +; +; MOV AH,GetExtCntry ; DOS 3.3 +; MOV AL,INFO_ID ( info type,-1 selects all) +; MOV BX,CODE_PAGE ( -1 = active code page ) +; MOV DX,COUNTRY_ID ( -1 = active country ) +; MOV CX,SIZE ( amount of data to return) +; LES DI,COUNTRY_INFO ( buffer for returned data ) +; INT 21 +; Function: +; give users extended country dependent information +; or capitalize chars +; Outputs: +; No Carry: +; extended country info is succesfully returned +; Carry: +; Register AX has the error code. +; AX=0, NO for YES/NO CHECK +; 1, YES + + + procedure $GetExtCntry,NEAR ; DOS 3.3 +ASSUME DS:NOTHING,ES:NOTHING + CMP AL,CAP_ONE_CHAR ;AN000;MS. < 20H ? + JAE capcap ;AN000;MS. + JMP notcap ;AN000;MS. yes +capcap: ;AN000; + TEST AL,UPPER_TABLE ;AN000;MS. which upper case table + JNZ fileupper ;AN000;MS. file upper case + MOV BX,OFFSET DOSGROUP:UCASE_TAB+2 ;AN000;MS. get normal upper case + JMP SHORT capit ;AN000;MS. +fileupper: ;AN000; + MOV BX,OFFSET DOSGROUP:FILE_UCASE_TAB+2;AN000;MS. get file upper case +capit: ;AN000; + CMP AL,CAP_ONE_CHAR ;AN000;;MS.cap one char ? + JNZ chkyes ;AN000;;MS. no + MOV AL,DL ;AN000;;MS. set up AL + invoke GETLET3 ;AN000;;MS. upper case it + invoke get_user_stack ;AN000;;MS. get user stack + MOV byte ptr [SI.user_DX],AL;AN000;;MS. user's DL=AL + JMP SHORT nono ;AN000;;MS. done +chkyes: ;AN000; + CMP AL,CHECK_YES_NO ;AN000;;MS. check YES or NO ? + JNZ capstring ;AN000;;MS. no + XOR AX,AX ;AN000;;MS. presume NO +IF DBCS ;AN000; + PUSH AX ;AN000;;MS. + MOV AL,DL ;AN000;;MS. + invoke TESTKANJ ;AN000;;MS. DBCS ? + POP AX ;AN000;;MS. + JNZ dbcs_char ;AN000;;MS. yes, return error +ENDIF ;AN000; + ;AN000; + CMP DL,NLS_YES ;AN000;;MS. is 'Y' ? + JZ yesyes ;AN000;;MS. yes + CMP DL,NLS_yes2 ;AN000;;MS. is 'y' ? + JZ yesyes ;AN000;;MS. yes + CMP DL,NLS_NO ;AN000;;MS. is 'N'? + JZ nono ;AN000;;MS. no + CMP DL,NLS_no2 ;AN000;;MS. is 'n' ? + JZ nono ;AN000;;MS. no +dbcs_char: ;AN000; + INC AX ;AN000;;MS. not YES or NO +yesyes: ;AN000' + INC AX ;AN000;;MS. return 1 +nono: ;AN000; + transfer SYS_RET_OK ;AN000;;MS. done +capstring: ;AN000; + MOV SI,DX ;AN000;;MS. si=dx + CMP AL,CAP_STRING ;AN000;;MS. cap string ? + JNZ capascii ;AN000;;MS. no + CMP CX,0 ;AN000;;MS. check count 0 + JZ nono ;AN000;;MS. yes finished +concap: ;AN000; + LODSB ;AN000;;MS. get char + IF DBCS ;AN000;;MS. + invoke TESTKANJ ;AN000;;MS. DBCS ? + JZ notdbcs ;AN000;;MS. no + INC SI ;AN000;;MS. skip 2 chars + DEC CX ;AN000;;MS. bad input, one DBCS char at end + JZ nono ;AN000;;MS. yes + JMP SHORT next99 ;AN000;;MS. +notdbcs: ;AN000; + ENDIF ;AN000; + + invoke GETLET3 ;AN000;;MS. upper case it + MOV byte ptr [SI-1],AL ;AN000;;MS. store back +next99: ;AN000; + LOOP concap ;AN000;;MS. continue + JMP nono ;AN000;;MS. done +capascii: ;AN000; + CMP AL,CAP_ASCIIZ ;AN000;;MS. cap ASCIIZ string ? + JNZ capinval ;AN000;;MS. no +concap2: ;AN000; + LODSB ;AN000;;MS. get char + CMP AL,0 ;AN000;;MS. end of string ? + JZ nono ;AN000;;MS. yes + IF DBCS ;AN000;;MS. + invoke TESTKANJ ;AN000;;MS. DBCS ? + JZ notdbcs2 ;AN000;;MS. no + CMP BYTE PTR [SI],0 ;AN000;;MS. bad input, one DBCS char at end + JZ nono ;AN000;;MS. yes + INC SI ;AN000;;MS. skip 2 chars + JMP concap2 ;AN000;;MS. +notdbcs2: ;AN000; + ENDIF ;AN000; + invoke GETLET3 ;AN000;;MS. upper case it + MOV byte ptr [SI-1],AL ;AN000;;MS. store back + JMP concap2 ;AN000;;MS. continue + + +notcap: + CMP CX,5 ; minimum size is 5 + JB sizeerror + context DS + MOV SI,OFFSET DOSGROUP:COUNTRY_CDPG + CMP DX,-1 ; active country ? + JNZ GETCDPG ; no + MOV DX,[SI.ccDosCountry] ; get active country id +GETCDPG: + CMP BX,-1 ; active code page? + JNZ CHKAGAIN ; no, check again + MOV BX,[SI.ccDosCodePage] ; get active code page id +CHKAGAIN: + CMP DX,[SI.ccDosCountry] ; same as active country id? + JNZ CHKNLS ; no + CMP BX,[SI.ccDosCodePage] ; same as active code page id? + JNZ CHKNLS ; no +CHKTYPE: + MOV BX,[SI.ccSysCodePage] ; bx = sys code page id +; CMP AL,SetALL ; select all? +; JNZ SELONE +; MOV SI,OFFSET DOSGROUP:COUNTRY_CDPG.ccNumber_of_entries +SELONE: + PUSH CX ; save cx + MOV CX,[SI.ccNumber_of_entries] + MOV SI,OFFSET DOSGROUP:COUNTRY_CDPG.ccSetUcase +NXTENTRY: + CMP AL,[SI] ; compare info type + JZ FOUNDIT + ADD SI,5 ; next entry + LOOP NXTENTRY + POP CX +capinval: + error error_Invalid_Function ; info type not found +FOUNDIT: + MOVSB ; move info id byte + POP CX ; retsore char count + CMP AL,SetCountryInfo ; select country info type ? + JZ setsize + MOV CX,4 ; 4 bytes will be moved + MOV AX,5 ; 5 bytes will be returned in CX +OK_RETN: + REP MOVSB ; copy info + MOV CX,AX ; CX = actual length returned + MOV AX,BX ; return sys code page in ax +GETDONE: + invoke get_user_stack ; return actual length to user's CX + MOV [SI.user_CX],CX + transfer SYS_RET_OK +setsize: + SUB CX,3 ; size after length field + CMP WORD PTR [SI],CX ; less than table size + JAE setsize2 ; no + MOV CX,WORD PTR [SI] ; truncate to table size +setsize2: + MOV ES:[DI],CX ; copy actual length to user's + ADD DI,2 ; update index + ADD SI,2 + MOV AX,CX + ADD AX,3 ; AX has the actual length + JMP OK_RETN ; go move it +CHKNLS: + XOR AH,AH + PUSH AX ; save info type + POP BP ; bp = info type + CallInstall NLSInstall,NLSFUNC,0 ; check if NLSFUNC in memory + CMP AL,0FFH + JZ NLSNXT ; in memory +sizeerror: + error error_Invalid_Function +NLSNXT: CallInstall GetExtInfo,NLSFUNC,2 ;get extended info + CMP AL,0 ; success ? + JNZ NLSERROR + MOV AX,[SI.ccSysCodePage] ; ax = sys code page id + JMP GETDONE +NLSERROR: + transfer SYS_RET_ERR ; return what is got from NLSFUNC + +EndProc $GetExtCntry + +BREAK <$GetSetCdPg - get or set global code page> +; +; Inputs: +; MOV AH,GetSetCdPg ; DOS 3.3 +; MOV AL,n ; n = 1 : get code page, n = 2 : set code page +; MOV BX,CODE_PAGE ( set code page only) +; INT 21 +; Function: +; get or set the global code page +; Outputs: +; No Carry: +; global code page is set (set global code page) +; BX = active code page id (get global code page) +; DX = system code page id (get global code page) +; Carry: +; Register AX has the error code. + + + procedure $GetSetCdPg,NEAR ; DOS 3.3 +ASSUME DS:NOTHING,ES:NOTHING + context DS + MOV SI,OFFSET DOSGROUP:COUNTRY_CDPG + CMP AL,1 ; get global code page + JNZ setglpg ; set global cod epage + MOV BX,[SI.ccDosCodePage] ; get active code page id + MOV DX,[SI.ccSysCodePage] ; get sys code page id + invoke get_user_stack +ASSUME DS:NOTHING + MOV [SI.user_BX],BX ; update returned bx + MOV [SI.user_DX],DX ; update returned dx +OK_RETURN: + transfer SYS_RET_OK +ASSUME DS:DOSGROUP +setglpg: + CMP AL,2 + JNZ nomem +;;;;;;; CMP BX,[SI.ccDosCodePage] ; same as active code page +;;;;;;; JZ OK_RETURN ; yes + MOV DX,[SI.ccDosCountry] + CallInstall NLSInstall,NLSFUNC,0 ; check if NLSFUNC in memory + CMP AL,0FFH + JNZ nomem ; not in memory + CallInstall SetCodePage,NLSFUNC,1 ;set the code page + CMP AL,0 ; success ? + JZ OK_RETURN ; yes + CMP AL,65 ; set device code page failed + JNZ seterr + MOV AX,65 + MOV [EXTERR],AX + MOV [EXTERR_ACTION],errACT_Ignore + MOV [EXTERR_CLASS],errCLASS_HrdFail + MOV [EXTERR_LOCUS],errLOC_SerDev + transfer From_GetSet + +seterr: + transfer SYS_RET_ERR +nomem: + error error_Invalid_Function ; function not defined +; +EndProc $GetSetCdPg + + + + +BREAK <$Get_Drive_Freespace -- Return bytes of free disk space on a drive> + procedure $GET_DRIVE_FREESPACE,NEAR +ASSUME DS:NOTHING,ES:NOTHING + +; Inputs: +; DL = Drive number +; Function: +; Return number of free allocation units on drive +; Outputs: +; BX = Number of free allocation units +; DX = Total Number of allocation units on disk +; CX = Sector size +; AX = Sectors per allocation unit +; = -1 if bad drive specified +; This call returns the same info in the same registers (except for FAT pointer) +; as the old FAT pointer calls + + context DS + MOV AL,DL + invoke GetThisDrv ; Get drive +SET_AX_RET: + JC BADFDRV + invoke DISK_INFO + XCHG DX,BX + JC SET_AX_RET ; User FAILed to I 24 + XOR AH,AH ; Chuck Fat ID byte +DoSt: + invoke get_user_stack +ASSUME DS:NOTHING + MOV [SI.user_DX],DX + MOV [SI.user_CX],CX + MOV [SI.user_BX],BX + MOV [SI.user_AX],AX + return +BADFDRV: +; MOV AL,error_invalid_drive ; Assume error + invoke FCB_RET_ERR + MOV AX,-1 + JMP DoSt +EndProc $GET_DRIVE_FREESPACE + +BREAK <$Get_DMA, $Set_DMA -- Get/Set current DMA address> + procedure $GET_DMA,NEAR +ASSUME DS:NOTHING,ES:NOTHING + +; Inputs: +; None +; Function: +; Get DISK TRANSFER ADDRESS +; Returns: +; ES:BX is current transfer address + + MOV BX,WORD PTR [DMAADD] + MOV CX,WORD PTR [DMAADD+2] + invoke get_user_stack + MOV [SI.user_BX],BX + MOV [SI.user_ES],CX + return +EndProc $GET_DMA + + procedure $SET_DMA,NEAR +ASSUME DS:NOTHING,ES:NOTHING + +; Inputs: +; DS:DX is desired new disk transfer address +; Function: +; Set DISK TRANSFER ADDRESS +; Returns: +; None + + MOV WORD PTR [DMAADD],DX + MOV WORD PTR [DMAADD+2],DS + return +EndProc $SET_DMA + +BREAK <$Get_Default_Drive, $Set_Default_Drive -- Set/Get default drive> + procedure $GET_DEFAULT_DRIVE,NEAR +ASSUME DS:NOTHING,ES:NOTHING + +; Inputs: +; None +; Function: +; Return current drive number +; Returns: +; AL = drive number + + MOV AL,[CURDRV] + return +EndProc $GET_DEFAULT_DRIVE + + procedure $SET_DEFAULT_DRIVE,NEAR +ASSUME DS:NOTHING,ES:NOTHING + +; Inputs: +; DL = Drive number for new default drive +; Function: +; Set the default drive +; Returns: +; AL = Number of drives, NO ERROR RETURN IF DRIVE NUMBER BAD + + MOV AL,DL + INC AL ; A=1, b=2... + invoke GetVisDrv ; see if visible drive + JC SETRET ; errors do not set +; LDS SI,ThisCDS ; get CDS +; TEST [SI].curdir_flags,curdir_splice ; was it spliced? +; JNZ SetRet ; yes, do not set + MOV [CURDRV],AL ; no, set +SETRET: + MOV AL,[CDSCOUNT] ; let user see what the count really is +RET17: return +EndProc $SET_DEFAULT_DRIVE + +BREAK <$Get_Interrupt_Vector - Get/Set interrupt vectors> + procedure $GET_INTERRUPT_VECTOR,NEAR +ASSUME DS:NOTHING,ES:NOTHING + +; Inputs: +; AL = interrupt number +; Function: +; Get the interrupt vector +; Returns: +; ES:BX is current interrupt vector + + CALL RECSET + LES BX,DWORD PTR ES:[BX] + invoke get_user_stack + MOV [SI.user_BX],BX + MOV [SI.user_ES],ES + return +EndProc $GET_INTERRUPT_VECTOR + + procedure $SET_INTERRUPT_VECTOR,NEAR +ASSUME DS:NOTHING,ES:NOTHING + +; Inputs: +; AL = interrupt number +; DS:DX is desired new interrupt vector +; Function: +; Set the interrupt vector +; Returns: +; None + + CALL RECSET + CLI ; Watch out!!!!! Folks sometimes use + MOV ES:[BX],DX ; this for hardware ints (like timer). + MOV ES:[BX+2],DS + STI + return +EndProc $SET_INTERRUPT_VECTOR + + IF ALTVECT +TABLE SEGMENT +VECIN: +; INPUT VECTORS +Public GSET001S,GSET001E +GSET001S label byte + DB 22H ; Terminate + DB 23H ; ^C + DB 24H ; Hard error + DB 28H ; Spooler +LSTVEC DB ? ; ALL OTHER + +VECOUT: +; GET MAPPED VECTOR + DB int_terminate + DB int_ctrl_c + DB int_fatal_abort + DB int_spooler +LSTVEC2 DB ? ; Map to itself + +NUMVEC = VECOUT-VECIN +GSET001E label byte +TABLE ENDS + ENDIF + +procedure RECSET,NEAR + + IF ALTVECT + context ES + MOV [LSTVEC],AL ; Terminate list with real vector + MOV [LSTVEC2],AL ; Terminate list with real vector + MOV CX,NUMVEC ; Number of possible translations + MOV DI,OFFSET DOSGROUP:VECIN ; Point to vectors + REPNE SCASB + MOV AL,ES:[DI+NUMVEC-1] ; Get translation + ENDIF + + XOR BX,BX + MOV ES,BX + MOV BL,AL + SHL BX,1 + SHL BX,1 + return +EndProc recset + +BREAK <$Char_Oper - hack on paths, switches so that xenix can look like PCDOS> +; +; input: AL = function: +; 0 - read switch char +; 1 - set switch char (char in DL) +; 2 - read device availability +; Always returns available +; 3 - set device availability +; No longer supported (NOP) +; output: (get) DL - character/flag +; + procedure $CHAR_OPER,NEAR + ASSUME DS:NOTHING,ES:NOTHING + context DS + CMP AL,1 + JB CharGetSw + JZ CharSetSw + CMP AL,3 + JB CharGetDev + JZ CharSetDev + MOV AL,-1 + return +CharGetSw: + MOV DL,chSwitch + JMP SHORT CharSet +CharSetSw: + MOV chSwitch,DL + return +CharGetDev: + MOV DL,-1 +CharSet: + Invoke Get_User_Stack + ASSUME DS:NOTHING + MOV [SI.User_DX],DX +CharSetDev: + return +EndProc $CHAR_OPER + +BREAK <$GetExtendedError - Return Extended DOS error code> +; +; input: None +; output: AX = Extended error code (0 means no extended error) +; BL = recommended action +; BH = class of error +; CH = locus of error +; ES:DI = may be pointer +; + procedure $GetExtendedError,NEAR + ASSUME DS:NOTHING,ES:NOTHING + Context DS + MOV AX,[EXTERR] + LES DI,[EXTERRPT] + MOV BX,WORD PTR [EXTERR_ACTION] ; BL = Action, BH = Class + MOV CH,[EXTERR_LOCUS] + invoke get_user_stack +ASSUME DS:NOTHING + MOV [SI.user_DI],DI + MOV [SI.user_ES],ES + MOV [SI.user_BX],BX + MOV [SI.user_CX],CX + transfer SYS_RET_OK +EndProc $GetExtendedError + +BREAK <$Get_Global_CdPg - Return Global Code Page> +; +; input: None +; output: AX = Global Code Page +; + procedure Get_Global_CdPg,NEAR + ASSUME DS:NOTHING,ES:NOTHING + PUSH SI + MOV SI,OFFSET DOSGROUP:COUNTRY_CDPG + MOV AX,CS:[SI.ccDosCodePage] + POP SI + return +EndProc Get_Global_CdPg + +;-------------------------------Start of DBCS 2/13/KK +BREAK + +ASSUME DS:NOTHING, ES:NOTHING + + procedure $ECS_call,NEAR + +; Inputs: +; AL = 0 get lead byte table +; on return DS:SI has the table location +; +; AL = 1 set / reset interim console flag +; DL = flag (00H or 01H) +; no return +; +; AL = 2 get interim console flag +; on return DL = current flag value +; +; AL = OTHER then error, and returns with: +; AX = error_invalid_function +; +; NOTE: THIS CALL DOES GUARANTEE THAT REGISTER OTHER THAN +; SS:SP WILL BE PRESERVED! + + IF DBCS ;AN000; + ;AN000; + or al, al ; AL = 0 (get table)? ;AN000; + je get_lbt ;AN000; + cmp al, SetInterimMode ; AL = 1 (set / reset interim flag)? ;AN000; + je set_interim ;AN000; + cmp al, GetInterimMode ; AL = 2 (get interim flag)? ;AN000; + je get_interim ;AN000; + error error_invalid_function ;AN000; + ;AN000; +get_lbt: ; get lead byte table ;AN000; + push ax ;AN000; + push bx ;AN000; + push ds ;AN000; + context DS ;AN000; + MOV BX,offset DOSGROUP:COUNTRY_CDPG.ccSetDBCS ;AN000; + MOV AX,[BX+1] ; set EV address to DS:SI ;AN000; + MOV BX,[BX+3] ;AN000; + ADD AX,2 ; Skip Lemgth ;AN000; + invoke get_user_stack ;AN000; + assume ds:nothing ;AN000; + MOV [SI.user_SI], AX ;AN000; + MOV [SI.user_DS], BX ;AN000; + pop ds ;AN000; + pop bx ;AN000; + pop ax ;AN000; + transfer SYS_RET_OK ;AN000; + +set_interim: ; Set interim console flag ;AN000; + push dx ;AN000; + and dl,01 ; isolate bit 1 ;AN000; + mov [InterCon], dl ;AN000; + push ds ;AN000; + mov ds, [CurrentPDB] ;AN000; + mov byte ptr ds:[PDB_InterCon], dl ; update value in pdb ;AN000; + pop ds ;AN000; + pop dx ;AN000; + transfer SYS_RET_OK ;AN000; + +get_interim: ;AN000; + push dx ;AN000; + push ds ;AN000; + mov dl,[InterCon] ;AN000; + invoke get_user_stack ; get interim console flag ;AN000; + assume ds:nothing ;AN000; + mov [SI.user_DX],DX ;AN000; + pop ds ;AN000; + pop dx ;AN000; + transfer SYS_RET_OK ;AN000; + ELSE ;AN000; + or al, al ; AL = 0 (get table)? ;AN000; + jnz okok ;AN000; +get_lbt: ;AN000; + invoke get_user_stack ;AN000; + assume ds:nothing ;AN000; + MOV [SI.user_SI], Offset Dosgroup:DBCS_TAB+2 ;AN000; + MOV [SI.user_DS], CS ;AN000; +okok: ;AN000; + transfer SYS_RET_OK ; ;AN000; + + ENDIF ;AN000; + +$ECS_call endp ;AN000; + +CODE ENDS + END diff --git a/v4.0/src/DOS/HANDLE.ASM b/v4.0/src/DOS/HANDLE.ASM new file mode 100644 index 0000000..e67c2ae --- /dev/null +++ b/v4.0/src/DOS/HANDLE.ASM @@ -0,0 +1,893 @@ +; SCCSID = @(#)handle.asm 1.1 85/04/10 +TITLE HANDLE - Handle-related system calls +NAME HANDLE +; +; Handle related system calls for MSDOS 2.X. Only top-level system calls +; are present. I/O specs are defined in DISPATCH. The system calls are: +; +; $Close written +; $Commit written DOS 3.3 F.C. 6/4/86 +; $ExtHandle written DOS 3.3 F.C. 6/4/86 +; $Read written +; Align_Buffer DOS 4.00 +; $Write written +; $LSeek written +; $FileTimes written +; $Dup written +; $Dup2 written +; +; Revision history: +; +; Created: MZ 28 March 1983 +; MZ 15 Dec 1982 Jeff Harbers and Multiplan hard disk copy +; rely on certain values in AX when $CLOSE +; succeeds even though we document it as +; always trashing AX. +; +; A000 version 4.00 Jan. 1988 +; + +.xlist +; +; get the appropriate segment definitions +; +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +include EA.inc +include version.inc +.cref +.list +.sall + + EXTRN DOS_Read:NEAR, DOS_Write:NEAR + +IF BUFFERFLAG + extrn save_user_map:near + extrn restore_user_map:near + extrn Setup_EMS_Buffers:near +ENDIF + + I_need ThisSFT,DWORD ; pointer to SFT entry + I_need DMAAdd,DWORD ; old-style DMA address + I_Need EXTERR_LOCUS,byte ; Extended Error Locus + I_need FailErr,BYTE ; failed error flag + I_need User_ID,WORD ; current effective user_id + i_need JShare,DWORD ; jump table + I_need CurrentPDB,WORD ; current process data block + I_need EXTOPEN_ON,BYTE ;AN000;FT. flag for extended open +; I_need XA_device,BYTE ;AN000; XA device + I_need XA_type,BYTE ;AN000; extended open subfunction +; I_need XA_handle,WORD ;AN000; handle + I_need THISCDS,DWORD ;AN000; + I_need DUMMYCDS,128 ;AN000; + I_need SAVE_ES,WORD ;AN000; saved ES + I_need SAVE_DI,WORD ;AN000; saved DI + I_need SAVE_DS,WORD ;AN000; saved DS + I_need SAVE_SI,WORD ;AN000; saved SI + I_need SAVE_CX,WORD ;AN000; saved CX + +IF BUFFERFLAG + + I_need BUF_EMS_MODE,BYTE + I_need BUF_EMS_LAST_PAGE,DWORD + I_need BUF_EMS_FIRST_PAGE,DWORD + I_need BUF_EMS_SAFE_FLAG,BYTE + I_need BUF_EMS_NPA640,WORD + I_need BUF_EMS_PAGE_FRAME,WORD + I_need BUF_EMS_PFRAME,WORD + I_need LASTBUFFER,DWORD + +ENDIF + +; I_need XA_ES,WORD ;AN000; extended find +; I_need XA_BP,WORD ;AN000; extended find +; I_need XA_from,BYTE ;AN000; for filetimes +if debug + I_need BugLev,WORD + I_need BugTyp,WORD +include bugtyp.asm +endif + +BREAK <$Close - return a handle to the system> + +; +; Assembler usage: +; MOV BX, handle +; MOV AH, Close +; INT int_command +; +; Error return: +; AX = error_invalid_handle +; +; No registers returned + +Procedure $Close,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP + fmt TypSysCall,LevLog,<"$p Close\n"> + fmt TypSysCall,LevArgs,<"$p Handle = $x\n">, +; +; Grab the SFT pointer from the JFN. +; + call CheckOwner ; get system file entry + JC CloseError ; error return + fmt TypAccess,LevSFN,<"$p Close SFT $x:$x\n">, + context DS ; For DOS_CLOSE + MOV WORD PTR [ThisSFT],DI ; save offset of pointer + MOV WORD PTR [ThisSFT+2],ES ; save segment value +; +; DS:SI point to JFN table entry. +; ES:DI point to SFT +; +; We now examine the user's JFN entry; If the file was a 70-mode file (network +; FCB, we examine the ref count on the SFT; if it was 1, we free the JFN. +; If the file was not a net FCB, we free the JFN too. +; + CMP ES:[DI].sf_ref_count,1 ; will the SFT become free? + JZ FreeJFN ; yes, free JFN anyway. + MOV AL,BYTE PTR ES:[DI].sf_mode + AND AL,sharing_mask + CMP AL,sharing_net_fcb + JZ PostFree ; 70-mode and big ref count => free it +; +; The JFN must be freed. Get the pointer to it and replace the contents with +; -1. +; +FreeJFN: + Invoke pJFNFromHandle ; d = pJFN (handle); + fmt TypAccess,LevSFN,<"$p Close jfn pointer $x:$x\n">, + MOV BYTE PTR ES:[DI],0FFh ; release the JFN +PostFree: +; +; ThisSFT is correctly set, we have DS = DOSGROUP. Looks OK for a DOS_CLOSE! +; + invoke DOS_Close +; +; DOS_Close may return an error. If we see such an error, we report it but +; the JFN stays closed because DOS_Close always frees the SFT! +; + JC CloseError + fmt TypSysCall,LevLog,<"$p: Close ok\n"> + MOV AH,close ; MZ Bogus multiplan fix + transfer Sys_Ret_OK +CloseError: + ASSUME DS:NOTHING + fmt TypSysCall,LevLog,<"$p: Close error $x\n">, + transfer Sys_Ret_Err +EndProc $Close + +BREAK <$Commit - commit the file> + +; +; Assembler usage: +; MOV BX, handle +; MOV AH, Commit +; INT int_command +; +; Error return: +; AX = error_invalid_handle +; +; No registers returned + +Procedure $Commit,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP +; +; Grab the SFT pointer from the JFN. +; + call CheckOwner ; get system file entry + JC Commiterror ; error return + context DS ; For DOS_COMMIT + MOV WORD PTR [ThisSFT],DI ; save offset of pointer + MOV WORD PTR [ThisSFT+2],ES ; save segment value +; +; ES:DI point to SFT +; +; +; ThisSFT is correctly set, we have DS = DOSGROUP. Looks OK for a DOS_COMMIT +; + invoke DOS_COMMIT +; +; + JC Commiterror + MOV AH,Commit ; + transfer Sys_Ret_OK +Commiterror: + ASSUME DS:NOTHING + transfer Sys_Ret_Err +EndProc $Commit + + +BREAK <$ExtHandle - extend handle count> + +; +; Assembler usage: +; MOV BX, Number of Opens Allowed (MAX=65534;66535 is +; MOV AX, 6700H reserved to mark SFT +; INT int_command busy ) +; +; Error return: +; AX = error_not_enough_memory +; or error_too_many_open_files +; No registers returned + +Procedure $ExtHandle,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP +; +; +; + XOR BP,BP ; 0: enlarge 1: shrink 2:psp + CMP BX,FilPerProc ; < 20 + JAE getpdb ; no + MOV BX,FilPerProc ; bx = 20 + +getpdb: + MOV ES,[CurrentPDB] ; get user process data block + MOV CX,ES:[PDB_JFN_Length] ; get number of handle allowed + CMP BX,CX ; the requested == current + JE ok_done ; yes and exit + JA larger ; go allocate new table + + MOV BP,1 ; shrink + MOV DS,WORD PTR ES:[PDB_JFN_Pointer+2] ; + MOV SI,BX ; + SUB CX,BX ; get difference +chck_handles: + CMP BYTE PTR DS:[SI],-1 ; scan through handles to ensure close + JNZ too_many_files ; status + INC SI + LOOP chck_handles + CMP BX,FilPerProc ; = 20 + JA larger ; no + + MOV BP,2 ; psp + MOV DI,PDB_JFN_Table ; es:di -> jfn table in psp + PUSH BX + JMP movhandl + +larger: + CMP BX,-1 ; 65535 is not allowed + JZ invalid_func + CLC + PUSH BX ; save requested number + ADD BX,0FH ; adjust to paragraph boundary + MOV CL,4 + RCR BX,CL ; DOS 4.00 fix ;AC000; + AND BX,1FFFH ; clear most 3 bits + + PUSH BP + invoke $ALLOC ; allocate memory + POP BP + JC no_memory ; not enough meory + + MOV ES,AX ; es:di points to new table memory + XOR DI,DI +movhandl: + MOV DS,[CurrentPDB] ; get user PDB address + + TEST BP,3 ; enlarge ? + JZ enlarge ; yes + POP CX ; cx = the amount you shrink + PUSH CX + JMP copy_hand +ok_done: + transfer Sys_Ret_OK +too_many_files: + MOV AL,error_too_many_open_files + transfer Sys_Ret_Err +enlarge: + MOV CX,DS:[PDB_JFN_Length] ; get number of old handles +copy_hand: + MOV DX,CX + LDS SI,DS:[PDB_JFN_Pointer] ; get old table pointer +ASSUME DS:NOTHING + REP MOVSB ; copy infomation to new table + + POP CX ; get new number of handles + PUSH CX ; save it again + SUB CX,DX ; get the difference + MOV AL,-1 ; set availability to handles + REP STOSB + + MOV DS,[CurrentPDB] ; get user process data block + CMP WORD PTR DS:[PDB_JFN_Pointer],0 ; check if original table pointer + JNZ update_info ; yes, go update PDB entries + PUSH BP + PUSH DS ; save old table segment + PUSH ES ; save new table segment + MOV ES,WORD PTR DS:[PDB_JFN_Pointer+2] ; get old table segment + invoke $DEALLOC ; deallocate old table meomory + POP ES ; restore new table segment + POP DS ; restore old table segment + POP BP + +update_info: + TEST BP,2 ; psp? + JZ non_psp ; no + MOV WORD PTR DS:[PDB_JFN_Pointer],PDB_JFN_Table ; restore + JMP final +non_psp: + MOV WORD PTR DS:[PDB_JFN_Pointer],0 ; new table pointer offset always 0 +final: + MOV WORD PTR DS:[PDB_JFN_Pointer+2],ES ; update table pointer segment + POP DS:[PDB_JFN_Length] ; restore new number of handles + transfer Sys_Ret_Ok +no_memory: + POP BX ; clean stack + MOV AL,error_not_enough_memory + transfer Sys_Ret_Err +invalid_func: + MOV AL,error_invalid_function + transfer Sys_Ret_Err +EndProc $ExtHandle + +BREAK <$READ - Read from a file handle> +; +; Assembler usage: +; LDS DX, buf +; MOV CX, count +; MOV BX, handle +; MOV AH, Read +; INT int_command +; AX has number of bytes read +; Errors: +; AX = read_invalid_handle +; = read_access_denied +; +; Returns in register AX + +procedure $READ,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP + fmt TypSysCall,LevLog,<"Read\n"> + fmt TypSysCall,LevArgs,<" Handle $x Cnt $x Buf $x:$x\n">, + MOV SI,OFFSET DOSGROUP:DOS_Read +ReadDo: + invoke pJFNFromHandle + JC ReadError + MOV AL,ES:[DI] + call CheckOwner ; get the handle + JNC ReadSetup ; no errors do the operation +ReadError: + fmt TypSysCall,LevLog,<"Read/Write error $x\n">, + transfer SYS_RET_ERR ; go to error traps +ReadSetup: + MOV WORD PTR [ThisSFT],DI ; save offset of pointer + MOV WORD PTR [ThisSFT+2],ES ; save segment value +;; Extended Open + TEST ES:[DI.sf_mode],INT_24_ERROR ;AN000;;EO. need i24 + JZ needi24 ;AN000;;EO. yes + OR [EXTOPEN_ON],EXT_OPEN_I24_OFF ;AN000;;EO. set it off +needi24: ;AN000; + +;; Extended Open + SaveReg <, > +;;;;; BAD SPOT FOR 286!!! SEGMENT ARITHMETIC!!! + CALL Align_Buffer ;AN000;MS. align user's buffer +;;;;; END BAD SPOT FOR 286!!! SEGMENT ARITHMETIC!!! + +IF BUFFERFLAG + +; int 3 +; cmp [BUF_EMS_MODE], -1 +; jz dos_call +; call choose_buf_page +; jc ReadError +; call save_user_map + +;dos_call: +ENDIF + context DS ; go for DOS addressability + CALL SI ; indirect call to operation + RestoreReg <, > + +IF BUFFERFLAG + pushf + push ax + push bx + + cmp cs:[BUF_EMS_MODE], -1 + jz dos_call_done + call restore_user_map + mov ax, word ptr cs:[BUF_EMS_LAST_PAGE] + cmp cs:[BUF_EMS_PFRAME], ax + je dos_call_done + mov word ptr cs:[LASTBUFFER], -1 + mov cs:[BUF_EMS_PFRAME], ax + mov ax, word ptr cs:[BUF_EMS_LAST_PAGE+2] + mov cs:[BUF_EMS_PAGE_FRAME], ax + mov cs:[BUF_EMS_SAFE_FLAG], 1 + call Setup_EMS_Buffers + +dos_call_done: + pop bx + pop ax + popf +ENDIF + +IF NOT BUFFERFLAG + JC ReadError ; if error, say bye bye +ELSE + jmp tmp_rerr +tmp_rerr: + jc ReadError +ENDIF + + MOV AX,CX ; get correct return in correct reg + fmt TypSysCall,LevLog,<"Read/Write cnt done $x\n">, + transfer sys_ret_ok ; successful return +EndProc $READ + +; +; Input: DS:DX points to user's buffer addr +; Function: rearrange segment and offset for READ/WRITE buffer +; Output: [DMAADD] set +; +; + +procedure Align_Buffer,NEAR ;AN000; + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP ;AN000; + MOV BX,DX ; copy offset + SaveReg ; don't stomp on count + MOV CL,4 ; bits to shift bytes->para + SHR BX,CL ; get number of paragraphs + RestoreReg ; get count back + MOV AX,DS ; get original segment + ADD AX,BX ; get new segment + MOV DS,AX ; in seg register + AND DX,0Fh ; normalize offset + MOV WORD PTR [DMAAdd],DX ; use user DX as offset + MOV WORD PTR [DMAAdd+2],DS ; use user DS as segment for DMA + return ;AN000; +EndProc Align_Buffer ;AN000; + +BREAK <$WRITE - write to a file handle> + +; +; Assembler usage: +; LDS DX, buf +; MOV CX, count +; MOV BX, handle +; MOV AH, Write +; INT int_command +; AX has number of bytes written +; Errors: +; AX = write_invalid_handle +; = write_access_denied +; +; Returns in register AX + +procedure $WRITE,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP + fmt TypSysCall,LevLog,<"Write\n"> + fmt TypSysCall,LevArgs,<" Handle $x Cnt $x Buf $x:$x\n">, + MOV SI,OFFSET DOSGROUP:DOS_Write + JMP ReadDo +EndProc $Write + +BREAK <$LSEEK - move r/w pointer> + +; +; Assembler usage: +; MOV DX, offsetlow +; MOV CX, offsethigh +; MOV BX, handle +; MOV AL, method +; MOV AH, LSeek +; INT int_command +; DX:AX has the new location of the pointer +; Error returns: +; AX = error_invalid_handle +; = error_invalid_function +; Returns in registers DX:AX + +procedure $LSEEK,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP + call CheckOwner ; get system file entry +LSeekError: + +IF BUFFERFLAG + JC TMP_RERR +ELSE + JC ReadError ; error return +ENDIF + CMP AL,2 ; is the seek value correct? + JBE LSeekDisp ; yes, go dispatch + MOV EXTERR_LOCUS,errLoc_Unk ; Extended Error Locus + error error_invalid_function ; invalid method +LSeekDisp: + CMP AL,1 ; best way to dispatch; check middle + JB LSeekStore ; just store CX:DX + JA LSeekEOF ; seek from end of file + ADD DX,WORD PTR ES:[DI.SF_Position] + ADC CX,WORD PTR ES:[DI.SF_Position+2] +LSeekStore: + MOV AX,CX ; AX:DX + XCHG AX,DX ; DX:AX is the correct value +LSeekSetpos: + MOV WORD PTR ES:[DI.SF_Position],AX + MOV WORD PTR ES:[DI.SF_Position+2],DX + invoke Get_user_stack + MOV DS:[SI.User_DX],DX ; return DX:AX + transfer SYS_RET_OK ; successful return + +LSeekEOF: + TEST ES:[DI.sf_flags],sf_isnet + JNZ Check_LSeek_Mode ; Is Net +LOCAL_LSeek: + ADD DX,WORD PTR ES:[DI.SF_Size] + ADC CX,WORD PTR ES:[DI.SF_Size+2] + JMP LSeekStore ; go and set the position + +Check_LSeek_Mode: + TEST ES:[DI.sf_mode],sf_isfcb + JNZ LOCAL_LSeek ; FCB treated like local file + MOV AX,ES:[DI.sf_mode] + AND AX,sharing_mask + CMP AX,sharing_deny_none + JZ NET_LSEEK ; LSEEK exported in this mode + CMP AX,sharing_deny_read + JNZ LOCAL_LSeek ; Treated like local Lseek +NET_LSEEK: +; JMP LOCAL_LSeek +; REMOVE ABOVE INSTRUCTION TO ENABLE DCR 142 + CallInstall Net_Lseek,multNet,33 + JNC LSeekSetPos + transfer SYS_RET_ERR + +EndProc $LSeek + +BREAK + +; +; Assembler usage: +; MOV AH, FileTimes (57H) +; MOV AL, func +; MOV BX, handle +; ; if AL = 1 then then next two are mandatory +; MOV CX, time +; MOV DX, date +; INT 21h +; ; if AL = 0 then CX/DX has the last write time/date +; ; for the handle. +; +; AL=02 get extended attributes +; BX=handle +; CX=size of buffer (0, return max size ) +; DS:SI query list (si=-1, selects all EA) +; ES:DI buffer to hold EA list +; +; AL=03 get EA name list +; BX=handle +; CX=size of buffer (0, return max size ) +; ES:DI buffer to hold name list +; +; AL=04 set extended attributes +; BX=handle +; ES:DI buffer of EA list +; +; +; +; +; Error returns: +; AX = error_invalid_function +; = error_invalid_handle +; + +procedure $File_Times,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP + CMP AL,2 ; correct subfunction? + JAE gsetxa + JMP filetimes_ok ; Yes, continue +;;;; DOS 4.00 ;AN000; +gsetxa: ;AN000; + EnterCrit critSFT ;AN000;;FT. enter critical section + CMP AL,4 ;AN000;;FT. =4 + JBE gshandle ;AN000;;FT. 2,3,4 do get/set by handle +funcerr: ;AN000; + JMP inval_func ;AN000;;FT. invalid function + ;AN000; +gshandle: ;AN000; + MOV [SAVE_ES],ES ;AN000;;FT. save regs + MOV [SAVE_DI],DI ;AN000;;FT. + MOV [SAVE_DS],DS ;AN000;;FT. save regs + MOV [SAVE_SI],SI ;AN000;;FT. + MOV [SAVE_CX],CX ;AN000;;FT. + MOV [XA_TYPE],AL ;AN000;;FT. + ;AN000; +; MOV [XA_handle],BX ;AN000; ;FT. save handle + CALL CheckOwner ;AN000; ;FT. get sf pointer + JNC getsetit ;AN000; ;FT. good handle + LeaveCrit critSFT ;AN000; ;FT. leave critical section + JMP LSeekError ;AN000; ;FT. turkey handle + ;AN000; +getsetit: ;AN000; + MOV WORD PTR [ThisSFT],DI ;AN000; ;FT. set ThisSFT + MOV WORD PTR [ThisSFT+2],ES ;AN000; ;FT. set ThisSFT +; TEST ES:[DI.sf_mode],INT_24_ERROR ;AN000;;FT. mask INT 24 +; JZ nomask ;AN000;;FT. no +; OR [EXTOPEN_ON],EXT_OPEN_I24_OFF ;AN000;;FT. set bit for I24 handler +nomask: ;AN000; + TEST ES:[DI.sf_flags],sf_isnet ;AN000;;FT. remote handle + JZ localhandle ;AN000;;FT. no + LeaveCrit critSFT ;AN000;;FT. doesn't support Network + + MOV BL,[XA_TYPE] ;AN000;;FT. +IFSsearch: ;AN000; + MOV AX,(multNET SHL 8) or 45 ;AN000;;FT. Get/Set XA support + INT 2FH ;AN000; + JC getseterror ;AN000;;FT. error + transfer SYS_RET_OK ;AN000;;FT. +localhandle: ;AN000; +; TEST ES:[DI.sf_flags],devid_device ;AN000;;FT. device +; JZ getsetfile8 ;AN000;;FT. no +; MOV [XA_device],1 ;AN000;;FT. indicating device +; JMP SHORT doXA ;AN000;;FT. do XA +getsetfile8: ;AN000; +; MOV [XA_device],0 ;AN000;;FT. indicating File +; LES BP,ES:[DI.sf_devptr] ;AN000;;FT. ES:BP -> DPB + +doXA: ;AN000; +; MOV [XA_from],By_XA ;AN000;;FT. from get/set XA +; PUSH [SAVE_ES] ;AN000;;FT. save XA list +; PUSH [SAVE_DI] ;AN000;;FT. save XA list + + invoke GetSet_XA ;AN000;;FT. issue Get/Set XA +; POP SI ;AN000;;FT. DS:SI -> XA list +; POP DS ;AN000; + JC getexit ;AN000;;FT. error +; CMP [XA_device],0 ;AN000;;FT. device ? +; JNZ ftok ;AN000;;FT. yes, exit +; MOV AX,4 ;AN000;;FT. function 4 for ShSU +; CMP [XA_type],4 ;AN000;;FT. set XA +; JNZ ftok ;AN000;;FT. no +; +; +; LES DI,[ThisSFT] ;AN000;;FT. es:di -> sft +; CMP WORD PTR [SI],0 ;AN000;;FT. null list ? +; JNZ do_share ;AN000;;FT. no + JMP SHORT ftok ;AN000;;FT. return +getexit: ;AN000;;FT. + LeaveCrit critSFT ;AN000;;FT. leave critical section + + +getseterror: ;AN000; + transfer SYS_RET_ERR ;AN000;;FT. mark file as dirty +inval_func: + +;;;;; DOS 4.00 + MOV EXTERR_LOCUS,errLoc_Unk ; Extended Error Locus + error error_invalid_function ; give bad return +filetimes_ok: + call CheckOwner ; get sf pointer + JNC gsdt + JMP LSeekError ; turkey handle +gsdt: + OR AL,AL ; is it Get? + JNZ filetimes_set ; no, go set the time + CLI + MOV CX,ES:[DI.sf_Time] ; suck out time + MOV DX,ES:[DI.sf_Date] ; and date + STI + invoke Get_user_stack ; obtain place to return it + MOV [SI.user_CX],CX ; and stash in time + MOV [SI.user_DX],DX ; and stask in date +ext_done: + transfer SYS_RET_OK ; and say goodnight +filetimes_set: + EnterCrit critSFT + MOV ES:[DI.sf_Time],CX ; drop in new time + MOV ES:[DI.sf_Date],DX ; and date + XOR AX,AX +do_share: +if installed + Call JShare + 14 * 4 +else + Call ShSU +endif +datetimeflg: + AND ES:[DI.sf_Flags],NOT devid_file_clean + OR ES:[DI.sf_Flags],sf_close_nodate +ftok: + LeaveCrit critSFT + transfer SYS_RET_OK ; mark file as dirty and return +EndProc $File_Times + +BREAK <$DUP - duplicate a jfn> +; +; Assembler usage: +; MOV BX, fh +; MOV AH, Dup +; INT int_command +; AX has the returned handle +; Errors: +; AX = dup_invalid_handle +; = dup_too_many_open_files +Procedure $DUP,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP + MOV AX,BX ; save away old handle in AX + invoke JFNFree ; free handle? into ES:DI, new in BX +DupErrorCheck: + JC DupErr ; nope, bye + SaveReg ; save away SFT + RestoreReg ; into convenient place DS:SI + XCHG AX,BX ; get back old handle + call CheckOwner ; get sft in ES:DI + JC DupErr ; errors go home + invoke DOS_Dup_Direct + invoke pJFNFromHandle ; get pointer + MOV BL,ES:[DI] ; get SFT number + MOV DS:[SI],BL ; stuff in new SFT + transfer SYS_RET_OK ; and go home +DupErr: transfer SYS_RET_ERR + +EndProc $Dup + +BREAK <$DUP2 - force a dup on a particular jfn> +; +; Assembler usage: +; MOV BX, fh +; MOV CX, newfh +; MOV AH, Dup2 +; INT int_command +; Error returns: +; AX = error_invalid_handle +; +Procedure $Dup2,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP + SaveReg ; save source + MOV BX,CX ; get one to close + invoke $Close ; close destination handle + RestoreReg ; old in AX, new in BX + invoke pJFNFromHandle ; get pointer + JMP DupErrorCheck ; check error and do dup +EndProc $Dup2 + +Break + +; +; CheckOwner - Due to the ability of the server to close file handles for a +; process without the process knowing it (delete/rename of open files, for +; example), it is possible for the redirector to issue a call to a handle +; that it soes not rightfully own. We check here to make sure that the +; issuing process is the owner of the SFT. At the same time, we do a +; SFFromHandle to really make sure that the SFT is good. +; +; Inputs: BX has the handle +; User_ID is the current user +; Output: Carry Clear => ES:DI points to SFT +; Carry Set => AX has error code +; Registers modified: none +; + +Procedure CheckOwner,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP + invoke SFFromHandle + retc + push ax + mov ax,user_id + cmp ax,es:[di].sf_UID + pop ax + retz + mov al,error_invalid_handle + stc + return +EndProc CheckOwner + +;------------------------------------------------------------------------- +; Function name : choose_buf_page +; Inputs : DMAADD = Xaddr +; cx = # of bytes to transfer +; Outputs : if NC +; +; SAFE_FLAG - 0 ==> page is safe. no need to +; detect collision between +; user & system buffer. +; SAFE_FLAG - 1 ==> page is unsafe. Must check +; for collision +; +; CY - error +; +; +; High Level Alogrithm: +; +; 1. If Xaddr. is above the first physical page above 640K +; 2. choose that page +; 3. set safe flag +; 4. else +; 5. choose highest page above 640K +; 6. If 6 or more pages above 640k +; 7. Set safe flag +; 8. else +; 9. if Xaddr. + # of bytes to transfer does not spill into the +; chosen page +; 10. set safe flag +; 11.else +; 12. clear safe flag +; 13.endif +; 14.endif +; 15.endif +; +;---------------------------------------------------------------------------- +;Procedure choose_buf_page,near +; +; assume cs:dosgroup, ds:nothing, es:nothing, ss:dosgroup +; +; push cx +; push bx +; push dx +; push si +; push ds +; push ax +; +; mov ax, word ptr [DMAADD+2] +; and ax, 0fc00h ; page segment of transfer segment +; +; cmp ax, word ptr [BUF_EMS_FIRST_PAGE] +; ja pick_first +; +; cmp [BUF_EMS_NPA640], 6 +; jae safe_pick_last +; +; add cx, word ptr [DMAADD] ; get final offset +; mov bx, cx +; +; mov cl, 4 +; shr bx, cl ; get # of paragraphs +; mov ax, word ptr [DMAADD+2] ; get initial segment +; add ax, bx ; get final segment +; +; and ax, 0fc00h +; cmp ax, word ptr [BUF_EMS_LAST_PAGE] +; jne safe_pick_last +; +; mov [BUF_EMS_SAFE_FLAG], 0 +; jmp fin_choose_page +; +;safe_pick_last: +; mov [BUF_EMS_SAFE_FLAG], 1 +; jmp fin_choose_page +; +;;pick_last: +;; mov ax, word ptr [BUF_EMS_LAST_PAGE] +;; mov [BUF_EMS_PFRAME], ax +;; mov ax, word ptr [BUF_EMS_LAST_PAGE+2] +;; mov [BUF_EMS_PAGE_FRAME], ax +;; xor ax, ax +;; jmp fin_choose_page +; +;pick_first: +; mov ax, word ptr [BUF_EMS_FIRST_PAGE] +; cmp [BUF_EMS_PFRAME], ax +; je fin_choose_page +; mov word ptr [LASTBUFFER], -1 +; mov [BUF_EMS_PFRAME], ax +; mov ax, word ptr [BUF_EMS_FIRST_PAGE+2] +; mov [BUF_EMS_PAGE_FRAME], ax +; mov [BUF_EMS_SAFE_FLAG], 1 +; call Setup_EMS_Buffers +; jmp fin_choose_page +; +;err_choose_page: +; stc +; +;fin_choose_page: +; clc +; +; pop ax +; pop ds +; pop si +; pop dx +; pop bx +; pop cx +; return +; +;EndProc choose_buf_page +; + +CODE ENDS +END + \ No newline at end of file diff --git a/v4.0/src/DOS/HIGHSW.ASM b/v4.0/src/DOS/HIGHSW.ASM new file mode 100644 index 0000000..9bd758f --- /dev/null +++ b/v4.0/src/DOS/HIGHSW.ASM @@ -0,0 +1,29 @@ +; SCCSID = @(#)highsw.asm 1.1 85/04/10 +TRUE EQU 0FFFFH +FALSE EQU NOT TRUE + +; Use the switches below to produce the standard Microsoft version or the IBM +; version of the operating system +MSVER EQU TRUE +IBM EQU FALSE +WANG EQU FALSE +ALTVECT EQU FALSE + +; Set this switch to cause DOS to move itself to the end of memory +HIGHMEM EQU TRUE + + IF IBM +ESCCH EQU 0 ; character to begin escape seq. +TOGLPRN EQU TRUE ;One key toggles printer echo +ZEROEXT EQU TRUE + ELSE + IF WANG ;Are we assembling for WANG? +ESCCH EQU 1FH ;Yes. Use 1FH for escape character + ELSE +ESCCH EQU 1BH + ENDIF +CANCEL EQU "X"-"@" ;Cancel with Ctrl-X +TOGLPRN EQU FALSE ;Separate keys for printer echo on + ;and off +ZEROEXT EQU TRUE + ENDIF diff --git a/v4.0/src/DOS/IFS.ASM b/v4.0/src/DOS/IFS.ASM new file mode 100644 index 0000000..2893f28 --- /dev/null +++ b/v4.0/src/DOS/IFS.ASM @@ -0,0 +1,523 @@ + + + +.xlist ;AN000; +include dosseg.asm ;AN000; + +CODE SEGMENT BYTE PUBLIC 'CODE' ;AN000; + ASSUME CS:DOSGROUP, SS:DOSGROUP ;AN000; +.xcref ;AN000; +include dossym.inc ;AN000; +include devsym.inc ;AN000; +include doscntry.inc ;AN000; +.cref ;AN000; +.list +StackSize = 180h ; gross but effective + + i_need VERFLG ; verify status flag ;AN000; + i_need CNTCFLAG ; break status flag ;AN000; + i_need CPSWFLAG ; CP switch logic ON/OFF ;AN000; + I_need CURRENTPDB,WORD ; Current process identifier ;AN000; + I_need HIGH_SECTOR,WORD ;AN000; + I_need BUF_HASH_COUNT,WORD ;AN000; + I_need FAILERR,WORD ;AN000; + I_need USER_ID,WORD ;AN000; + I_need CALLDEVAD,DWORD ; ;AN000; + I_need SYSINITVAR,WORD ;AN000; + I_need MYNAME,16 ; NetBIOS name ;AN000; + I_need RETRYCOUNT,WORD ; retry count ;AN000; + I_need COUNTRY_CDPG,BYTE ;AN000; + i_need DAY,BYTE ; date ;AN000; + i_need MONTH,BYTE ;AN000; + i_need YEAR,WORD ;AN000; + i_need CURBUF,DWORD ;AN000; + i_need IFS_DRIVER_ERR,WORD ;AN000; + i_need DOS34_FLAG,WORD ; IFS function Read/Write flag ;AN000; + i_need Callback_SS,WORD ; ;AN000; + i_need Callback_SP,WORD ;AN000; + i_need SaveBX,WORD ;AN000; + i_need Temp_Var,WORD ;AN000; + i_need INDOS,BYTE ;AN000; + i_need DskStack,BYTE ;AN000; + i_need IOStack,BYTE ;AN000; + i_need Callback_flag,BYTE ;AN000; + +DOSINFO STRUC ;AN000; +bsize dw 0 ;AN000; +files dw 0 ;AN000; +fcbs1 dw 0 ;AN000; +fcbs2 dw 0 ;AN000; +buffers dw 0 ;AN000; + dw 0 ;AN000; +lastdrv dw 0 ;AN000; +secsize dw 0 ;AN000; +DosInfo ENDS ;AN000; + + + + extrn ABSDRD:NEAR ;AN000; + extrn ABSDWRT:NEAR ;AN000; + extrn READTIME:NEAR ;AN000; + extrn CHECKFLUSH:NEAR ;AN000; + extrn GETCURHEAD:NEAR ;AN000; + + +;****************************************************************************** +; * +; * MODULE: IFS_DOSCALL +; * +; * FUNCTION: IFS to DOS function request dispatcher +; * +; * FUNCTION: This procedure dispatches the IFS DOS service requests +; * by calling various DOS service routines +; * +; * CALLING SEQUENCE: +; * +; * CALL DWORD PTR IFS_DOSCALL@ +; * +; * +; * RETURN SEQUENCE: +; * +; * If AX = 0 No error +; * +; * If AX <> 0 Error +; * AX = Error Code: +; * +; * +; * INTERNAL REFERENCES: None +; * +; * +; * EXTERNAL REFERENCES: STRATEGY, INTERRUPT, ABSDRD, ABSDWRT, +; * FIND_SECTOR, MARK_SECTOR, WRITE_BUFFR, +; * READ_BUFFR, WRITE_BUFFR, FREE_BUFFR, +; * GET_DOS_INFO, FLUSH_BUFF +; * +; * NOTES: None +; * +; * REVISION HISTORY: New +; * +; * COPYRIGHT: "MS DOS IFS Function" +; * "Version 1.00 (C) Copyright 1988 Microsoft Corporation" +; * "Licensed Material - Program Property of Microsoft" +; * +; ************************************************************************* + + + + + +PROCEDURE IFS_DOSCALL,FAR ;AN000; + assume DS:NOTHING,ES:NOTHING ;AN000; + + CLI ; ;AN000; + CMP AH,39 ; ;AN000; + JNZ others ; ;AN000; + INC CS:[INDOS] ; in DOS ;AN000; + JMP Dosend ; ;AN000; +others: + CMP AH,40 ; ;AN000; + JNZ others2 ; ;AN000; + DEC CS:[INDOS] ; out DOS ;AN000; + JMP Dosend ; ;AN000; +others2: + CMP AH,38 ; ;AN000; + JNZ not_stack ; ;AN000; + PUSH CS ; ;AN000; + POP DS ; ;AN000; + MOV SI,OFFSET DOSGROUP:IOSTACK ;AN000; + MOV CX,stacksize ;AN000; + JMP Dosend ; ;AN000; + ; ;AN000; +not_stack: ; ;AN000; + MOV CS:[Temp_Var],DS; save ds for strcmp strcpy ;AN000; + PUSH CS ; ;AN000; + POP DS ; ;AN000; + assume DS:DOSGROUP ;AN000; + INC [INDOS] ; in DOS ;AN000; + PUSH CX ; save cx ;AN000; + PUSH DX ; save cx ;AN000; + MOV CX,SS ; cx=stack ;AN000; + MOV DX,CS ; cx=stack ;AN000; + CMP CX,DX ; dosgroup stack ? ;AN000; + POP DX ; save cx ;AN000; + POP CX ; restore cx ;AN000; + JZ withSS_SP ; yes ;AN000; + MOV [Callback_SS],SS ;save SS:SP ;AN000; + MOV [Callback_SP],SP ;AN000; + MOV [SaveBX],BX ; ;AN000; + MOV BX,CS ; prepare system stack ;AN000; + MOV SS,BX ; ;AN000; + MOV SP,OFFSET DOSGROUP:DSKSTACK ;AN000; + MOV BX,[SaveBX] ; ;AN000; + MOV [Callback_flag],1 ;set flag ;AN000; +withSS_SP: ; ;AN000; + STI ;AN000; + ASSUME DS:NOTHING ;AN000; +; OR [DOS34_FLAG],Force_I24_Fail ;AN000; +; ;AN000; +; cmp ah,0 ; call Strategy routine ?? ;AN000; +; jne dos_chk_ah1 ; jump if not ;AN000; +; CALL STRATEGY ; else call strategy routine ;AN000; +; jmp dos_exit ; then exit ;AN000; + ;AN000; +;Dos_Chk_Ah1: ;AN000; +; cmp ah,1 ; call interrupt routine ;AN000; +; jne dos_chk_ah2 ; jump if not ;AN000; +; CALL INTERRUPT ; else call interrupt routine ;AN000; +; jmp dos_exit ; then exit ;AN000; + ;AN000; +;Dos_Chk_Ah2: ;AN000; +; cmp ah,4 ;AN000; +; jae Dos_Chk_Ah8 ;AN000; +; mov High_Sector,si ; save HI sector word ;AN000; +; mov dx,di ; save low sector ;AN000; +; push es ;AN000; +; invoke FIND_DPB ; ds:si -> DPB ;AN000; +; mov bp,si ;AN000; +; push ds ;AN000; +; pop es ; es:bp -> DPB ;AN000; +; pop ds ; DS:BX-->Input buffer ;AN000; +; +; cmp ah,2 ; absolute read ?? ;AN000; +; jne dos_chk_ah3 ; jump if not ;AN000; +; +; invoke DSKREAD ; else do absolute read ;AN000; +; jmp dos_exit ; then return ;AN000; + +;Dos_Chk_Ah3: ;AN000; +; invoke DSKWRITE ; do absolute write ;AN000; +; jmp dos_exit ; then exit ;AN000; + + + +Dos_chk_ah32: ;AN000; + cmp ah,32 + jne str_cmp ;AN000; + CALL GET_DOS_INFO ; else get DOS information ;AN000; + jmp SHORT dos_exit ;AN000; ;AN000; +str_cmp: ;AN000; + mov DS,[Temp_Var] ; restore DS ;AN000; + cmp ah,36 ;AN000; + jne str_cpy ;AN000; + invoke strcmp ; string compare ;AN000; + jmp SHORT dos_exit ;AN000; +str_cpy: ;AN000; + cmp ah,37 ;AN000; + jne dos_error ;AN000; + invoke strcpy ; string copy ;AN000; + jmp SHORT dos_exit ;AN000; + +Dos_Error: ;AN000; + stc + ;AN000; +Dos_Exit: ;AN000; + CLI ;AN000; + PUSHF ;AN000; + AND [DOS34_FLAG],No_Force_I24_Fail ;AN000; + DEC [INDOS] ; exit DOS ;AN000; + CMP [Callback_flag],0 ;from dosgroup + JZ noSS_SP ;yes ;AN000; + MOV [Callback_flag],0 ; ;AN000; + POPF ;AN000; + MOV SP,CS:[Callback_SP]; ;AN000; + MOV SS,CS:[Callback_SS]; restore user's SS:SP ;AN000; + JMP SHORT DOSend ;AN000; +noSS_SP: ;AN000; + POPF +Dosend: + STI ; ;AN000; + + ret ;return ;AN000; + + +ENDPROC IFS_DOSCALL ;AN000; + + + + + +; **************************************************************************** +; * +; * MODULE: STRATEGY +; * +; * FUNCTION: Call Strategy Routine +; * +; * FUNCTION: This procedure dispatches the IFS DOS service requests +; * by calling various DOS service functions +; * +; * INPUT: ES:BX ---> Device Request Header +; * AL = Drive # +; * +; * CALL STRATEGY +; * +; * OUTPUT: output of driver +; * +; * INTERNAL REFERENCES: None +; * +; * +; * EXTERNAL REFERENCES: GETTHISDRV +; * +; * NOTES: None +; * +; * REVISION HISTORY: New +; * +; ************************************************************************* + +;PROCEDURE STRATEGY,NEAR ;AN000; + +; INVOKE FIND_DPB ; get DPB from drive number ;AN000; +; ; DS:SI-->DPB for drive ;AN000; +; LDS DI,DS:[SI.DPB_Driver_Addr] ; get driver addres from DPB ;AN000; +; MOV DX,WORD PTR [DI.SDEVSTRAT] ;get strategy routine address;AN000; +;Driver_Call: ;AN000; +; MOV WORD PTR [CALLDEVAD],DX ; save it ;AN000; +; MOV WORD PTR [CALLDEVAD+2],DS ; ;AN000; +; CALL DWORD PTR [CALLDEVAD] ; call strategy routine ;AN000; +;STRAT_Exit: ;AN000; +; RET ; return ;AN000; + +;ENDPROC STRATEGY ;AN000; + + + + + + + + +; **************************************************************************** +; * +; * MODULE: INTERRUPT +; * +; * FUNCTION: This procedure calls the interrupt routine of the drive +; * specified in the drive#. +; * +; * INPUT: AL = Drive # +; * +; * +; * OUTPUT: output of driver +; * +; * +; * INTERNAL REFERENCES: None +; * +; * +; * EXTERNAL REFERENCES: FIND_DPB +; * +; * NOTES: None +; * +; * REVISION HISTORY: New +; * +; ************************************************************************* + +;PROCEDURE INTERRUPT,NEAR ;AN000; + +; INVOKE FIND_DPB ; get DPB from drive number ;AN000; +; LDS DI,DS:[SI.DPB_Driver_Addr] ; get driver addres from DPB ;AN000; +; MOV DX,WORD PTR [DI.SDEVINT] ; get interrupt routine addrs;AN000; +; JMP Driver_Call ;AN000; + +;ENDPROC INTERRUPT ;AN000; + + + + + + + + +; ************************************************************************* * +; * +; * MODULE: Get_Dos_Info +; * +; * FUNCTION: Get DOS information +; * +; * INPUT: AL = Dos info code +; * +; * OUTPUT: Dos Information in registers +; * +; * INTERNAL REFERENCES: None +; * +; * +; * EXTERNAL REFERENCES: READTIME, $GETEXTCNTRY +; * +; * NOTES: None +; * +; * REVISION HISTORY: New +; * +; ************************************************************************* + +PROCEDURE GET_DOS_INFO,NEAR ;AN000; + + cmp al,0 ; TIME and DATE ?? ;AN000; + jne chk_al1 ;AN000; + + Invoke ReadTime ; get time in CX:DX ;AN000; + + push cx ; save time ;AN000; + push dx ;AN000; + + MOV CX,[YEAR] ;AN000; + ADD CX,1980 ;AN000; + MOV DX,WORD PTR [DAY] ; fetch both day and month ;AN000; + + pop bx ; bh = seconds bl = hundredths ;AN000; + pop ax ; ah = hour al = minutes ;AN000; + ; cx = year dh = month ;AN000; + jmp get_info_exit ;AN000; + + +chk_al1: ; Active process info ?? ;AN000; + cmp al,1 ;AN000; + jne chk_al2 ; no, try next ;AN000; + MOV BX,[CurrentPDB] ; BX = active process ID ;AN000; + mov DX,[User_ID] ; User ID ;AN000; + jmp get_info_exit ; exit ;AN000; + + +chk_al2: ;AN000; +; cmp al,2 ; get CPSW info ?? ;AN000; +; jne chk_al3 ; jump if not ;AN000; +; MOV SI,OFFSET DOSGROUP:COUNTRY_CDPG ;AN000; +; MOV BX,[SI.ccDosCodePage] ; get dos code page id in BX ;AN000; +; MOV DL,CPSWFLAG ; get CP Switch status ;AN000; +; jmp get_info_exit ; exit ;AN000; + + +chk_al3: +; cmp al,3 ; get CTRL BRK status ?? ;AN000; +; jne chk_al4 ;AN000; +; mov dl,CNTCFLAG ; DL = break status flag ;AN000; +; jmp get_info_exit ; exit ;AN000; + + +chk_al4: +; cmp al,4 ; get Verify status ?? ;AN000; +; jne chk_al5 +; mov dl,VERFLG ; DL = verify status flag ;AN000; +; jmp get_info_exit ; exit ;AN000; + + +chk_al5: + cmp al,5 ; Config.sys info ?? ;AN000; + jne chk_al6 ;AN000; + + mov si,OFFSET DOSGROUP:SYSINITVAR ; DS:SI-->SysInitVar ;AN000; + push ds ;AN000; + push si ;AN000; + lds si,[si].Sysi_SFT ; get SFT address ;AN000; + mov ax,[si].SFCount ; get number of files ;AN000; + lds si,[si].SFlink ; get next SFT table ;AN000; + cmp si,-1 ; end of table ;AN000; + jz nomore ; ;AN000; + add ax,[si].SFCount ; ;AN000; +nomore: ; ;AN000; + mov es:[di].files,ax ; save files= value ;AN000; + pop si ;AN000; + pop ds ;AN000; + mov ax,[si].Sysi_MaxSec ; get maximum sector size ;AN000; + mov es:[di].secsize,ax ; save files= value ;AN000; + mov ax,[si].Sysi_Keep ; ;AN000; + mov es:[di].fcbs2,ax ; ;AN000; + lds si,[si].Sysi_FCB ; get FCB address ;AN000; + mov ax,[si].SFCount ; get number of fcbs ;AN000; + mov es:[di].fcbs1,ax ; save fcbs= value ;AN000; + jmp get_info_exit ;AN000; + + + +chk_al6: ;AN000; + cmp al,6 ; get machine name ?? ;AN000; + jne chk_al7 ; no, check next function ;AN000; + context DS ;AN000; + mov si,offset DOSGroup:MyName ; DS:SI-->name string ;AN000; + ; ES:DI-->return buffer ;AN000; + add di,2 ; skip max return size ;AN000; + mov cx,15 ; name size ;AN000; +Chk6_Loop: ;AN000; + rep movsb ; copy machine name to return buffer;AN000; + xor al,al ; set 16th byte is 0 ;AN000; + stosb ;AN000; + jmp get_info_exit ; return ;AN000; + ;AN000; + ;AN000; +Chk_Al7: ;AN000; +; cmp al,7 ; get country information ?? ;AN000; +; jne chk_al8 ; no, try next function ;AN000; +; mov al,dl ; AL = info ID ;AN000; +; mov bx,-1 ; select active code page ;AN000; +; mov dx,-1 ; select active country ;AN000; +; mov cx,-1 ; get all ;AN000; +; INVOKE $getExtCntry ; get country info ;AN000; +; jmp SHORT Get_Info_Exit ; exit ;AN000; + + +Chk_Al8: ;AN000; + cmp al,8 ; get share retry count ?? ;AN000; + jne bad_param ; no, Bad parameter ;AN000; + mov bx,RetryCount ; BX = Share retry count ;AN000; + jmp SHORT Get_Info_Exit ; exit ;AN000; + +Bad_Param: ; Bad parameter ;AN000; + stc ; ;AN000; + +Get_Info_Exit: ; exit ;AN000; + + ret ;AN000; + + +ENDPROC GET_DOS_INFO ;AN000; + + + + + + + + +; ************************************************************************* * +; * +; * MODULE: $IFS_IOCTL +; * +; * FUNCTION: Handle IFS Driver IOCTL calls +; * +; * INPUT: AH = 6B function code +; * AL = XX 00 = Drive IOCTL, 01 = Psudo device IOCTL +; * CX = 00 Reserved +; * BL = XX Device Number +; * DS:DX Pointer to Buffer +; * +; * OUTPUT: +; * IF CARRY = 0 No Error +; * IF CARRY = 1 Error +; * AX = ERROR CODE +; * +; * INTERNAL REFERENCES: None +; * +; * +; * EXTERNAL REFERENCES: INT 2F +; * +; * NOTES: None +; * +; * REVISION HISTORY: New +; ************************************************************************* + +PROCEDURE $IFS_IOCTL,NEAR ;AN000; + + PUSH AX ;AN000; + MOV AX,(multnet SHL 8) OR 47 ; pass control to IFS Func ;AN000; + INT 2FH ;AN000; + POP BX ;AN000; + JC ABB_ERR ;AN000; + TRANSFER SYS_RET_OK ; return ;AN000; + +ABB_ERR: ;AN000; + transfer SYS_RET_ERR ; error return ;AN000; + +ENDPROC $IFS_IOCTL ;AN000; + + + +CODE ENDS ;AN000; + END ;AN000; + + diff --git a/v4.0/src/DOS/IOCTL.ASM b/v4.0/src/DOS/IOCTL.ASM new file mode 100644 index 0000000..8007244 --- /dev/null +++ b/v4.0/src/DOS/IOCTL.ASM @@ -0,0 +1,745 @@ +; SCCSID = @(#)IOCTL.INC 1.15 85/09/05 +TITLE IOCTL - IOCTL system call +NAME IOCTL + +; +; +; IOCTL system call. +; +; +; $IOCTL +; +; Revision history: +; +; Created: ARR 4 April 1983 +; +; GenericIOCTL added: KGS 22 April 1985 +; +; A000 version 4.00 Jan. 1988 + + + +.xlist +; +; get the appropriate segment definitions +; +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +include ioctl.inc +include ifssym.inc ;AN000; +.cref +.list + + i_need THISCDS,DWORD + i_need IOCALL,BYTE + i_need IOMED,BYTE + i_need IOSCNT,WORD + i_need IOXAD,DWORD + I_need RetryCount,WORD + I_need RetryLoop,WORD + I_need EXTERR_LOCUS,BYTE + I_need OPENBUF,BYTE + I_need ExtErr,WORD + I_need DrvErr,BYTE + I_need USER_IN_AX,WORD ;AN000; + I_need Temp_Var2,WORD ;AN000; + +BREAK + +; +; Assembler usage: +; MOV BX, Handle +; MOV DX, Data +; +; (or LDS DX,BUF +; MOV CX,COUNT) +; +; MOV AH, Ioctl +; MOV AL, Request +; INT 21h +; +; AH = 0 Return a combination of low byte of sf_flags and device driver +; attribute word in DX, handle in BX: +; DH = high word of device driver attributes +; DL = low byte of sf_flags +; 1 Set the bits contained in DX to sf_flags. DH MUST be 0. Handle +; in BX. +; 2 Read CX bytes from the device control channel for handle in BX +; into DS:DX. Return number read in AX. +; 3 Write CX bytes to the device control channel for handle in BX from +; DS:DX. Return bytes written in AX. +; 4 Read CX bytes from the device control channel for drive in BX +; into DS:DX. Return number read in AX. +; 5 Write CX bytes to the device control channel for drive in BX from +; DS:DX. Return bytes written in AX. +; 6 Return input status of handle in BX. If a read will go to the +; device, AL = 0FFh, otherwise 0. +; 7 Return output status of handle in BX. If a write will go to the +; device, AL = 0FFh, otherwise 0. +; 8 Given a drive in BX, return 1 if the device contains non- +; removable media, 0 otherwise. +; 9 Return the contents of the device attribute word in DX for the +; drive in BX. 0200h is the bit for shared. 1000h is the bit for +; network. 8000h is the bit for local use. +; A Return 8000h if the handle in BX is for the network or not. +; B Change the retry delay and the retry count for the system. BX is +; the count and CX is the delay. +; +; Error returns: +; AX = error_invalid_handle +; = error_invalid_function +; = error_invalid_data +; +;------------------------------------------------------------------------------- +; +; This is the documentation copied from DOS 4.0 it is much better +; than the above +; +; There are several basic forms of IOCTL calls: +; +; +; ** Get/Set device information: ** +; +; ENTRY (AL) = function code +; 0 - Get device information +; 1 - Set device information +; (BX) = file handle +; (DX) = info for "Set Device Information" +; EXIT 'C' set if error +; (AX) = error code +; 'C' clear if OK +; (DX) = info for "Get Device Information" +; USES ALL +; +; +; ** Read/Write Control Data From/To Handle ** +; +; ENTRY (AL) = function code +; 2 - Read device control info +; 3 - Write device control info +; (BX) = file handle +; (CX) = transfer count +; (DS:DX) = address for data +; EXIT 'C' set if error +; (AX) = error code +; 'C' clear if OK +; (AX) = count of bytes transfered +; USES ALL +; +; +; ** Read/Write Control Data From/To Block Device ** +; +; ENTRY (AL) = function code +; 4 - Read device control info +; 5 - Write device control info +; (BL) = Drive number (0=default, 1='A', 2='B', etc) +; (CX) = transfer count +; (DS:DX) = address for data +; EXIT 'C' set if error +; (AX) = error code +; 'C' clear if OK +; (AX) = count of bytes transfered +; USES ALL +; +; +; ** Get Input/Output Status ** +; +; ENTRY (AL) = function code +; 6 - Get Input status +; 7 - Get Output Status +; (BX) = file handle +; EXIT 'C' set if error +; (AX) = error code +; 'C' clear if OK +; (AL) = 00 if not ready +; (AL) = FF if ready +; USES ALL +; +; +; ** Get Drive Information ** +; +; ENTRY (AL) = function code +; 8 - Check for removable media +; 9 - Get device attributes +; (BL) = Drive number (0=default, 1='A', 2='B', etc) +; EXIT 'C' set if error +; (AX) = error code +; 'C' clear if OK +; (AX) = 0/1 media is removable/fixed (func. 8) +; (DX) = device attribute word (func. 9) +; USES ALL +; +; +; ** Get Redirected bit ** +; +; ENTRY (AL) = function code +; 0Ah - Network stuff +; (BX) = file handle +; EXIT 'C' set if error +; (AX) = error code +; 'C' clear if OK +; (DX) = SFT flags word, 8000h set if network file +; USES ALL +; +; +; ** Change sharer retry parameters ** +; +; ENTRY (AL) = function code +; 0Bh - Set retry parameters +; (CX) = retry loop count +; (DX) = number of retries +; EXIT 'C' set if error +; (AX) = error code +; 'C' clear if OK +; USES ALL +; +; +; ================================================================= +; +; ** New Standard Control ** +; +; ALL NEW IOCTL FACILITIES SHOULD USE THIS FORM. THE OTHER +; FORMS ARE OBSOLETE. +; +; ================================================================= +; +; ENTRY (AL) = function code +; 0Ch - Control Function subcode +; (BX) = File Handle +; (CH) = Category Indicator +; (CL) = Function within category +; (DS:DX) = address for data, if any +; (SI) = Passed to device as argument, use depends upon function +; (DI) = Passed to device as argument, use depends upon function +; EXIT 'C' set if error +; (AX) = error code +; 'C' clear if OK +; (SI) = Return value, meaning is function dependent +; (DI) = Return value, meaning is function dependent +; (DS:DX) = Return address, use is function dependent +; USES ALL +; +; ============== Generic IOCTL Definitions for DOS 3.2 ============ +; (See dos/ioctl.mac for more info) +; +; ENTRY (AL) = function code +; 0Dh - Control Function subcode +; (BL) = Drive Number (0 = Default, 1= 'A') +; (CH) = Category Indicator +; (CL) = Function within category +; (DS:DX) = address for data, if any +; (SI) = Passed to device as argument, use depends upon function +; (DI) = Passed to device as argument, use depends upon function +; +; EXIT 'C' set if error +; (AX) = error code +; 'C' clear if OK +; (DS:DX) = Return address, use is function dependent +; USES ALL +; + + procedure $IOCTL,NEAR + ASSUME DS:NOTHING,ES:NOTHING + MOV SI,DS ; Stash DS for calls 2,3,4 and 5 + context DS + CMP AL,3 + JBE ioctl_check_char ; char device + JMP ioctl_check_block ; Block device +ioctl_check_char: + invoke SFFromHandle ; ES:DI -> SFT + JNC ioctl_check_permissions ; have valid handle +ioctl_bad_handle: + error error_invalid_handle + +ioctl_check_permissions: + CMP AL,2 + JAE ioctl_control_string + CMP AL,0 + MOV AL,BYTE PTR ES:[DI.sf_flags]; Get low byte of flags + JZ ioctl_read ; read the byte + PUSH DX ;AN000;MS. + AND DH,0FEH ;AN000;MS.allow DH=01H + POP DX ;AN000;MS. + JZ ioctl_check_device ; can I set with this data? + error error_invalid_data ; no DH <> 0 + +ioctl_bad_funj2: + JMP ioctl_bad_fun + +ioctl_check_device: + TEST AL,devid_device ; can I set this handle? + JZ do_exception ; no, it is a file. + OR DL,devid_device ; Make sure user doesn't turn off the + ; device bit!! He can muck with the + ; others at will. + MOV [EXTERR_LOCUS],errLOC_SerDev + MOV BYTE PTR ES:[DI.sf_flags],DL ;AC000;MS.; Set flags +do_exception: + OR BYTE PTR ES:[DI.sf_flags+1],DH;AN000;MS.;set 100H bit for disk full + + transfer SYS_RET_OK + + + + + +ioctl_read: + MOV [EXTERR_LOCUS],errLOC_Disk + XOR AH,AH + TEST AL,devid_device ; Should I set high byte + JZ ioctl_no_high ; no + MOV [EXTERR_LOCUS],errLOC_SerDev + LES DI,ES:[DI.sf_devptr] ; Get device pointer + MOV AH,BYTE PTR ES:[DI.SDEVATT+1] ; Get high byte +ioctl_no_high: + MOV DX,AX + invoke get_user_stack + MOV [SI.user_DX],DX + transfer SYS_RET_OK + +ioctl_control_string: + TEST ES:[DI.sf_flags],devid_device ; can I? + JNZ ioctl_ctl_str_1 + JMP ioctl_bad_fun ; No it is a file +ioctl_ctl_str_1: + TEST ES:[DI.sf_flags],sf_isnet ;AN000;IFS.; IFS ? + JZ localrw ;AN000;IFS.; no + JMP callifs ;AN000;IFS.; call IFS +localrw: + MOV [EXTERR_LOCUS],errLOC_SerDev + LES DI,ES:[DI.sf_devptr] ; Get device pointer + XOR BL,BL ; Unit number of char dev = 0 + JMP ioctl_do_string + +ioctl_get_devj: + JMP ioctl_get_dev + +ioctl_check_block: + DEC AL + DEC AL ; 4=2,5=3,6=4,7=5,8=6,9=7,10=8,11=9 + CMP AL,3 + JBE ioctl_get_devj + CMP AL,6 + JAE ioctl_rem_media_check + + MOV AH,1 + SUB AL,4 ; 6=0,7=1 + JZ ioctl_get_status + MOV AH,3 +ioctl_get_status: + PUSH AX + invoke GET_IO_SFT + POP AX + JNC DO_IOFUNC + JMP ioctl_bad_handle ; invalid SFT + +DO_IOFUNC: + invoke IOFUNC + MOV AH,AL + MOV AL,0FFH + JNZ ioctl_status_ret + INC AL +ioctl_status_ret: + transfer SYS_RET_OK + +ioctl_rem_media_check: ; 4=2,5=3,6=4,7=5,8=6,9=7,10=8,11=9 + JE ioctl_rem_mediaj + + SUB AL,7 ; 9=0,10=1,11=2,12=3,13=4,14=5,15=6 + JNZ Rem_med_chk_1 + JMP Ioctl_Drive_attr + +ioctl_rem_mediaj: + jmp ioctl_rem_media + +ioctl_bad_funj4: + jmp ioctl_bad_fun + +Rem_med_chk_1: + + DEC AL ; 10=0,11=1,12=2,13=3,14=4,15=5 + jnz Set_Retry_chk + Jmp Ioctl_Handle_redirj + +Set_Retry_chk: + DEC AL ; 11=0,12=1,13=2,14=3,15=4 + JZ Set_Retry_Parameters + + DEC AL ; 12=0,13=1,14=2,15=3 + JZ GENERICIOCTLHANDLE + + DEC AL ; 13=0,14=1,15=2 + JZ GENERICIOCTL + + CMP AL,2 + JA ioctl_bad_funj4 + JMP ioctl_drive_owner +Set_Retry_Parameters: + MOV RetryLoop,CX ; 0 retry loop count allowed + OR DX,DX ; zero retries not allowed + JNZ goodtr + JMP IoCtl_Bad_Fun +goodtr: + MOV RetryCount,DX ; Set new retry count +doneok: + transfer Sys_Ret_Ok ; Done + +; Generic IOCTL entry point. +; here we invoke the Generic IOCTL using the IOCTL_Req structure. +; SI:DX -> Users Device Parameter Table +; IOCALL -> IOCTL_Req structure +GENERICIOCTLHANDLE: + invoke SFFromHandle ; Get SFT for device. + jnc goodh + JMP ioctl_bad_handlej +goodh: +; test word ptr [DI.sf_flags],sf_isnet + CALL TEST_IFS_REMOTE ;AN000;;IFS. test if remote + JZ okokok ;AN000;;IFS. + jmp ioctl_bad_fun ; Cannot do this over net. +okokok: + TEST [DI.sf_flags],sf_isnet ;AN000;IFS.; local IFS + JNZ callifs ;AN000;IFS.; yes + + + mov [EXTERR_LOCUS],ErrLOC_Serdev + les di,es:[di.sf_devptr] ; Get pointer to device. + jmp short Do_GenIOCTL + +GENERICIOCTL: + mov [EXTERR_LOCUS],ErrLOC_Disk + cmp ch,IOC_DC ; Only disk devices are allowed to use + jne ioctl_bad_fun ; no handles with Generic IOCTL. + CALL Check_If_Net ; ES:DI := Get_hdr_block of device in BL + JNZ ioctl_bad_fun ; There are no "net devices", and they + PUSH ES ; certainly don't know how to do this ;AN000; + PUSH DI ;AN000;IFS. + LES DI,[THISCDS] ;AN000;IFS. ; + TEST ES:[DI.curdir_flags],curdir_isnet;AN000;IFS. ; local IFS ? + POP DI ;AN000;IFS. + POP ES ;AN000;IFS. + JZ Do_GenIOCTL ;AN000;IFS. ; no +callifs: + CMP byte ptr [User_In_AX+1],69H ;AN000; ;IFS. + JNZ is44xx ;AN000; ;IFS. + MOV AX,440DH ;AN000; ;IFS. + PUSH AX ;AN000; ;IFS. + JMP SHORT callrose ;AN000; ;IFS. +is44xx: + PUSH [User_In_AX] ;AN000; ;IFS. call IFSFUNC +callrose: + MOV DS,SI ;AN000; ;IFS. + MOV AX,(multNET SHL 8) or 43 ;AN000; ;IFS. + INT 2FH ;AN000; ;IFS. + POP BX ;AN000; ;IFS. + JNC doneok ;AN000; ;IFS. + MOV DI,AX ;AN000; ;IFS. + JMP device_err ;AN000; ;IFS. +Do_GenIOCTL: + test ES:[DI.SDEVATT],DEV320 ; Can device handle Generic IOCTL funcs + jz ioctl_bad_fun + PUSH ES ; DEVIOCALL2 expects Device header block + PUSH DI ; in DS:SI + ;set up Generic IOCTL Request Block + MOV byte ptr IOCALL.ReqLen,(size IOCTL_Req) + MOV byte ptr IOCALL.ReqFunc,GENIOCTL + MOV byte ptr IOCALL.ReqUnit,BL + MOV byte ptr IOCALL.MajorFunction,CH + MOV byte ptr IOCALL.MinorFunction,CL + MOV word ptr IOCALL.Reg_SI,SI + MOV word ptr IOCALL.Reg_DI,DI + MOV word ptr IOCALL.GenericIOCTL_Packet,DX + MOV word ptr IOCALL.GenericIOCTL_Packet + 2,SI + + MOV BX,offset DOSGROUP:IOCALL + + PUSH SS + POP ES + +ASSUME DS:NOTHING ; DS:SI -> Device header. + POP SI + POP DS + jmp ioctl_do_IO ; Perform Call to device driver + +IOCtl_Handle_RedirJ: + JMP IOCTL_Handle_Redir +ioctl_bad_fun: + error error_invalid_function + +ioctl_bad_handlej: + jmp ioctl_bad_handle + +; Function 8 +ioctl_rem_media: + CALL Check_If_Net + JNZ ioctl_bad_fun ; There are no "net devices", and they + ; certainly don't know how to do this + ; call. + TEST ES:[DI.SDEVATT],DEVOPCL ; See if device can + JZ ioctl_bad_fun ; NO + MOV [IOCALL.REQFUNC],DEVRMD + MOV AL,REMHL + MOV AH,BL ; Unit number + MOV WORD PTR [IOCALL.REQLEN],AX + XOR AX,AX + MOV [IOCALL.REQSTAT],AX + PUSH ES + POP DS +ASSUME DS:NOTHING + MOV SI,DI ; DS:SI -> driver + PUSH SS + POP ES + MOV BX,OFFSET DOSGROUP:IOCALL ; ES:BX -> Call header + SaveReg + invoke DEVIOCALL2 + RestoreReg + MOV AX,[IOCALL.REQSTAT] ; Get Status word + AND AX,STBUI ; Mask to busy bit + MOV CL,9 + SHR AX,CL ; Busy bit to bit 0 + transfer SYS_RET_OK + +; Function 9 +Ioctl_Drive_attr: + +;;;;; MOV AL,BL ;AC000;; Drive +;;;;; invoke GETTHISDRV ;AC000; +;;;;; ;AC000; +;;;;; JC ioctl_drv_err ; drive not valid + call Get_Driver_BL + JC ioctl_drv_err ; drive not valid + MOV AX,[Temp_Var2] ;AN000;IFS. + mov dx,word ptr es:[di.SDEVATT] ; get device attribute word + MOV BL,AL ; Phys letter to BL (A=0) + LES DI,[THISCDS] +;;;;; TEST ES:[DI.curdir_flags],curdir_isnet + CALL TEST_IFS_REMOTE2 ;AN000;IFS. test if remote + JZ IOCTLShare + OR DX,1000h +IOCTLShare: + Context DS +ASSUME DS:NOTHING + MOV SI,OFFSET DOSGROUP:OPENBUF + ADD BL,"A" + MOV [SI],BL + MOV WORD PTR [SI+1],003AH ; ":",0 + MOV AX,0300H + CLC + INT int_IBM + JNC ioctlLocal ; Not shared + OR DX,0200H ; Shared, bit 9 +IOCTLLocal: + TEST ES:[DI].curdir_flags,curdir_local + JZ ioctl_set_dx + OR DX,8000h + +ioctl_set_DX: + invoke get_user_stack + MOV [SI.user_DX],DX + transfer SYS_RET_OK + +ioctl_drv_err: + MOV AL,[DrvErr] ;AN000;IFS. DrvErr is saved in GetThisDrv + transfer SYS_RET_ERR ;AN000;IFS. + +; Function 10 +Ioctl_Handle_redir: + invoke SFFromHandle ; ES:DI -> SFT + JNC ioctl_got_sft ; have valid handle + error error_invalid_handle + +ioctl_got_sft: + MOV DX,ES:[DI.sf_flags] ; Get flags + JMP ioctl_set_DX + +ioctl_bad_funj: + JMP ioctl_bad_fun + +ioctl_get_dev: + DOSAssume CS,,"IOCTL/IOCtl_Get_Dev" + CALL Check_If_Net + JNZ ioctl_bad_funj ; There are no "net devices", and they + ; certainly don't know how to do this + ; call. +ioctl_do_string: + TEST ES:[DI.SDEVATT],DEVIOCTL; See if device accepts control + JZ ioctl_bad_funj ; NO + DEC AL + DEC AL + JZ ioctl_control_read + MOV [IOCALL.REQFUNC],DEVWRIOCTL + JMP SHORT ioctl_control_call +ioctl_control_read: + MOV [IOCALL.REQFUNC],DEVRDIOCTL +ioctl_control_call: + MOV AL,DRDWRHL +ioctl_setup_pkt: + MOV AH,BL ; Unit number + MOV WORD PTR [IOCALL.REQLEN],AX + XOR AX,AX + MOV [IOCALL.REQSTAT],AX + MOV [IOMED],AL + MOV [IOSCNT],CX + MOV WORD PTR [IOXAD],DX + MOV WORD PTR [IOXAD+2],SI + PUSH ES + POP DS +ASSUME DS:NOTHING + MOV SI,DI ; DS:SI -> driver + PUSH SS + POP ES + MOV BX,OFFSET DOSGROUP:IOCALL ; ES:BX -> Call header +ioctl_do_IO: + invoke DEVIOCALL2 + TEST [IOCALL.REQSTAT],STERR ;Error? + JNZ Ioctl_string_err + MOV AX,[IOSCNT] ; Get actual bytes transferred + transfer SYS_RET_OK + +Ioctl_string_err: + MOV DI,[IOCALL.REQSTAT] ;Get Error +device_err: + AND DI,STECODE ; mask out irrelevant bits + MOV AX,DI + invoke SET_I24_EXTENDED_ERROR + mov ax, cs:extErr + transfer SYS_RET_ERR + +Get_Driver_BL: + DOSAssume CS,,"Get_Driver_BL" + ASSUME ES:NOTHING +; BL is drive number (0=default) +; Returns pointer to device in ES:DI, unit number in BL if carry clear +; No regs modified + + PUSH AX + MOV AL,BL ; Drive + invoke GETTHISDRV + JNC ioctl_goodrv ;AC000;IFS. + CMP AL,error_not_dos_disk ;AN000;IFS. if unknow media then + JZ ioctl_goodrv ;AN000;IFS. let it go + STC ;AN000;IFS. else + JMP SHORT ioctl_bad_drv ;AN000;IFS. error +ioctl_goodrv: + XOR BL,BL ; Unit zero on Net device + MOV [EXTERR_LOCUS],errLOC_Net + LES DI,[THISCDS] +; TEST ES:[DI.curdir_flags],curdir_isnet + CALL TEST_IFS_REMOTE2 ;AN000;;IFS. test if remote + LES DI,ES:[DI.curdir_devptr]; ES:DI -> Dpb or net dev + JNZ got_dev_ptr ; Is net + MOV [EXTERR_LOCUS],errLOC_Disk + MOV BL,ES:[DI.dpb_UNIT] ; Unit number + LES DI,ES:[DI.dpb_driver_addr] ; Driver addr +got_dev_ptr: + CLC + MOV [Temp_Var2],AX ;AN000;IFS. +ioctl_bad_drv: + POP AX + return + +; +; Checks if the device is over the net or not. Returns result in ZERO flag. +; If no device is found, the return address is popped off the stack, and a +; jump is made to ioctl_drv_err. +; +; On Entry: +; Registers same as those for Get_Driver_BL +; +; On Exit: +; ZERO flag - set if not a net device +; - reset if net device +; ES:DI -> the device +; +Check_If_Net: + CALL Get_Driver_BL + JC ioctl_drv_err_pop ; invalid drive letter +entry TEST_IFS_REMOTE2 + PUSH ES + PUSH DI + LES DI,[THISCDS] + TEST ES:[DI.curdir_flags],curdir_isnet + JZ belocal ;AN000; ;IFS. + LES DI,ES:[DI.curdir_ifs_hdr] ;AN000; ;IFS. test if remote +TEST_REMOTE: ;AN000; + TEST ES:[DI.ifs_attribute],IFSREMOTE;AN000; ;IFS. +belocal: + POP DI + POP ES + ret + +ioctl_drv_err_pop: + pop ax ; pop off return address + jmp ioctl_drv_err + +ioctl_bad_funj3: + jmp ioctl_bad_fun + +ioctl_string_errj: + jmp ioctl_string_err + +; Functions 14 and 15 +ioctl_drive_owner: + Call Check_If_Net + JNZ ioctl_bad_funj3 ; There are no "net devices", and they + ; certainly don't know how to do this + ; call. + TEST ES:[DI.SDEVATT],DEV320 ; See if device can handle this + JZ ioctl_bad_funj3 ; NO + dec al + jz GetOwner + MOV [IOCALL.REQFUNC],DEVSETOWN + jmp short ioctl_do_own +GetOwner: + MOV [IOCALL.REQFUNC],DEVGETOWN +ioctl_do_own: + MOV AL,OWNHL + MOV AH,BL ; Unit number + MOV WORD PTR [IOCALL.REQLEN],AX + XOR AX,AX + MOV [IOCALL.REQSTAT],AX + PUSH ES + POP DS +ASSUME DS:NOTHING + MOV SI,DI ; DS:SI -> driver + PUSH SS + POP ES + MOV BX,OFFSET DOSGROUP:IOCALL ; ES:BX -> Call header + SaveReg + invoke DEVIOCALL2 + RestoreReg + test [IOCALL.REQSTAT],STERR + jnz ioctl_string_errj + MOV AL,BYTE PTR [IOCALL.REQUNIT] ; Get owner returned by device + ; owner returned is 1-based. + transfer SYS_RET_OK + +EndProc $IOCTL + + +;Input: ES:DI -> SFT +;Functions: test if a remote file +;Output: Z flag set, local file +; + + procedure TEST_IFS_REMOTE,NEAR ;AN000; + ASSUME DS:NOTHING,ES:NOTHING ;AN000; + + TEST ES:[DI.sf_flags],sf_isnet ;AN000;;IFS. ifs ? + JZ nonifs ;AN000;;IFS. no + PUSH ES ;AN000;;IFS. save regs + PUSH DI ;AN000;;IFS. + LES DI,ES:[DI.sf_IFS_hdr] ;AN000;;IFS. get ifs header + JMP TEST_REMOTE ;AN000;;IFS. +nonifs: ;AN000; + return ;AN000;;IFS. +EndProc TEST_IFS_REMOTE ;AN000; + +CODE ENDS +END diff --git a/v4.0/src/DOS/ISEARCH.ASM b/v4.0/src/DOS/ISEARCH.ASM new file mode 100644 index 0000000..bfae821 --- /dev/null +++ b/v4.0/src/DOS/ISEARCH.ASM @@ -0,0 +1,364 @@ +; SCCSID = @(#)isearch.asm 1.1 85/04/10 +TITLE DOS_SEARCH - Internal SEARCH calls for MS-DOS +NAME DOS_SEARCH +; Low level routines for doing local and NET directory searches +; +; DOS_SEARCH_FIRST +; DOS_SEARCH_NEXT +; RENAME_NEXT +; +; Revision history: +; +; Created: ARR 30 March 1983 +; A000 version 4.00 Jan. 1988 +; A001 PTM 3564 -- serach for fastopen + +; +; get the appropriate segment definitions +; +.xlist +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +INCLUDE fastopen.inc +INCLUDE fastxxxx.inc +.cref +.list + +Installed = TRUE + + i_need NoSetDir,BYTE + i_need Creating,BYTE + i_need THISCDS,DWORD + i_need CURBUF,DWORD + i_need DMAADD,DWORD + i_need DummyCDS,128 + i_need THISDPB,DWORD + i_need THISDRV,BYTE + i_need NAME1,BYTE + i_need ATTRIB,BYTE + i_need DIRSTART,WORD + i_need LASTENT,WORD + i_need FOUND_DEV,BYTE + I_need WFP_Start,WORD + i_need EXTERR_LOCUS,BYTE + i_need FastopenFlg,BYTE + I_need DOS34_FLAG,WORD + +; Inputs: +; [WFP_START] Points to WFP string ("d:/" must be first 3 chars, NUL +; terminated) +; [CURR_DIR_END] Points to end of Current dir part of string +; ( = -1 if current dir not involved, else +; Points to first char after last "/" of current dir part) +; [THISCDS] Points to CDS being used +; (Low word = -1 if NUL CDS (Net direct request)) +; [SATTRIB] Is attribute of search, determines what files can be found +; [DMAADD] Points to 53 byte buffer +; Function: +; Initiate a search for the given file spec +; Outputs: +; CARRY CLEAR +; The 53 bytes ot DMAADD are filled in as follows: +; +; LOCAL +; Drive Byte (A=1, B=2, ...) High bit clear +; NEVER STORE DRIVE BYTE AFTER found_it +; 11 byte search name with Meta chars in it +; Search Attribute Byte, attribute of search +; WORD LastEnt value +; WORD DirStart +; 4 byte pad +; 32 bytes of the directory entry found +; NET +; 21 bytes First byte has high bit set +; 32 bytes of the directory entry found +; +; CARRY SET +; AX = error code +; error_no_more_files +; No match for this file +; error_path_not_found +; Bad path (not in curr dir part if present) +; error_bad_curr_dir +; Bad path in current directory part of path +; DS preserved, others destroyed + + procedure DOS_SEARCH_FIRST,NEAR + DOSAssume CS,,"DOS_Search_First" + ASSUME ES:NOTHING + + LES DI,[THISCDS] + CMP DI,-1 + JNZ TEST_RE_NET +IF NOT Installed + transfer NET_SEQ_SEARCH_FIRST +ELSE + MOV AX,(multNET SHL 8) OR 25 + INT 2FH + return +ENDIF + +TEST_RE_NET: + TEST ES:[DI.curdir_flags],curdir_isnet + JZ LOCAL_SEARCH_FIRST +IF NOT Installed + transfer NET_SEARCH_FIRST +ELSE + MOV AX,(multNET SHL 8) OR 27 + INT 2FH + return +ENDIF + +LOCAL_SEARCH_FIRST: + EnterCrit critDisk + TEST [DOS34_FLAG],SEARCH_FASTOPEN ;AN000; + JZ NOFN ;AN000; + OR [FastOpenflg],Fastopen_Set ;AN000; +NOFN: ;AN000; + MOV [NoSetDir],1 ; if we find a dir, don't change to it + CALL CHECK_QUESTION ;AN000;;FO. is '?' in path + JNC norm_getpath ;AN000;;FO. no + AND [FastOpenflg],Fast_yes ;AN000;;FO. reset fastopen +norm_getpath: + invoke GetPath +getdone: + JNC find_check_dev + JNZ bad_path + OR CL,CL + JZ bad_path +find_no_more: + MOV AX,error_no_more_files +BadBye: + AND CS:[FastOpenflg],Fast_yes ;AN000;;FO. reset fastopen + + STC + LeaveCrit critDisk + return + +bad_path: + MOV AX,error_path_not_found + JMP BadBye + +find_check_dev: + OR AH,AH + JNS found_entry + MOV [LastEnt],-1 ; Cause DOS_SEARCH_NEXT to fail + INC [Found_Dev] ; Tell DOS_RENAME we found a device +found_entry: +; +; We set the physical drive byte here Instead of after found_it; Doing +; a search-next may not have wfp_start set correctly +; + LES DI,[DMAADD] + MOV SI,WFP_Start ; get pointer to beginning + LODSB + SUB AL,'A'-1 ; logical drive + STOSB ; High bit not set (local) +found_it: + LES DI,[DMAADD] + INC DI + PUSH DS ;FO.;AN001; save ds + TEST [Fastopenflg],Set_For_Search ;FO.;AN001; from fastopen + JZ notfast ;FO.;AN001; + MOV SI,BX ;FO.;AN001; + MOV DS,WORD PTR [CURBUF+2] ;FO.;AN001; + JMP SHORT movmov ;FO.;AN001; + + +notfast: + MOV SI,OFFSET DOSGROUP:NAME1; find_buf 2 = formatted name +movmov: +; Special E5 code + MOVSB + CMP BYTE PTR ES:[DI-1],5 + JNZ NOTKANJB + MOV BYTE PTR ES:[DI-1],0E5H +NOTKANJB: + + MOV CX,10 + REP MOVSB + POP DS ;FO.;AN001; restore ds + + + MOV AL,[Attrib] + STOSB + PUSH AX ; Save AH device info + MOV AX,[LastEnt] + STOSW + MOV AX,[DirStart] + STOSW +; 4 bytes of 21 byte cont structure left for NET stuff + ADD DI,4 + POP AX ; Recover AH device info + OR AH,AH + JS DOSREL ; Device entry is DOSGROUP relative + CMP WORD PTR [CURBUF],-1 + JNZ OKSTORE + TEST [FastOPenFlg],Set_For_Search ;AN000;;FO. from fastopen and is good + JNZ OKSTORE ;AN000;;FO. + + + + ; The user has specified the root directory itself, rather than some + ; contents of it. We can't "find" that. + MOV WORD PTR ES:[DI-8],-1 ; Cause DOS_SEARCH_NEXT to fail by + ; stuffing a -1 at Lastent + JMP find_no_more + +OKSTORE: + MOV DS,WORD PTR [CURBUF+2] +ASSUME DS:NOTHING +DOSREL: + MOV SI,BX ; SI-> start of entry + +; NOTE: DOS_RENAME depends on BX not being altered after this point + + MOV CX,SIZE dir_entry +;;;;; 7/29/86 + MOV AX,DI ; save the 1st byte addr + REP MOVSB + MOV DI,AX ; restore 1st byte addr + CMP BYTE PTR ES:[DI],05H ; special char check + JNZ NO05 + MOV BYTE PTR ES:[DI],0E5H ; convert it back to E5 +NO05: + +;;;;; 7/29/86 + AND CS:[FastOpenflg],Fast_yes ;AN000;;FO. reset fastopen + context DS + CLC + LeaveCrit critDisk + return + +EndProc DOS_SEARCH_FIRST + +BREAK + +; Inputs: +; [DMAADD] Points to 53 byte buffer returned by DOS_SEARCH_FIRST +; (only first 21 bytes must have valid information) +; Function: +; Look for subsequent matches +; Outputs: +; CARRY CLEAR +; The 53 bytes at DMAADD are updated for next call +; (see DOS_SEARCH_FIRST) +; CARRY SET +; AX = error code +; error_no_more_files +; No more files to find +; DS preserved, others destroyed + + procedure DOS_SEARCH_NEXT,NEAR + DOSAssume CS,,"DOS_Search_Next" + ASSUME ES:NOTHING + + LES DI,[DMAADD] + MOV AL,ES:[DI] + TEST AL,80H ; Test for NET + JZ LOCAL_SEARCH_NEXT +IF NOT Installed + transfer NET_SEARCH_NEXT +ELSE + MOV AX,(multNET SHL 8) OR 28 + INT 2FH + return +ENDIF + +LOCAL_SEARCH_NEXT: +;AL is drive A=1 + MOV [EXTERR_LOCUS],errLOC_Disk + EnterCrit critDisk + MOV WORD PTR ThisCDS,OFFSET DOSGROUP:DummyCDS + MOV WORD PTR ThisCDS+2,CS + ADD AL,'A'-1 + invoke InitCDS + +; invoke GetThisDrv ; Set CDS pointer + + JC No_files ; Bogus drive letter + LES DI,[THISCDS] ; Get CDS pointer + LES BP,ES:[DI.curdir_devptr]; Get DPB pointer + invoke GOTDPB ; [THISDPB] = ES:BP + + mov AL,ES:[BP.dpb_drive] + mov ThisDrv,AL + + MOV WORD PTR [CREATING],0E500H + MOV [NoSetDir],1 ; if we find a dir, don't change to it + LDS SI,[DMAADD] +ASSUME DS:NOTHING + LODSB ; Drive Byte + +; DEC AL +; MOV [THISDRV],AL + + entry RENAME_NEXT ; Entry used by DOS_RENAME + + context ES ; THIS BLOWS ES:BP POINTER TO DPB + MOV DI,OFFSET DOSGROUP:NAME1 + MOV CX,11 + REP MOVSB ; Search name + LODSB ; Attribute + MOV [ATTRIB],AL + LODSW ; LastEnt + OR AX,AX + JNS cont_load +No_files: + JMP find_no_more + +cont_load: + PUSH AX ; Save LastEnt + LODSW ; DirStart + MOV BX,AX + context DS + LES BP,[THISDPB] ; Recover ES:BP + invoke SetDirSrch + JNC SEARCH_GOON + POP AX ; Clean stack + JMP No_files + +SEARCH_GOON: + invoke StartSrch + POP AX + invoke GetEnt + JC No_files + invoke NextEnt + JC No_files + XOR AH,AH ; If Search_Next, can't be a DEV + JMP found_it + +EndProc DOS_SEARCH_NEXT + + +;Input: [WFP_START]= pointer to final path +;Function: check '?' char +;Output: carry clear, if no '?' +; carry set, if '?' exists + + procedure CHECK_QUESTION,NEAR ;AN000; + ASSUME ES:NOTHING,DS:NOTHING ;AN000; + + PUSH CS ;AN000;;FO. + POP DS ;AN000;;FO. ds:si -> final path + MOV SI,[WFP_START] ;AN000;;FO. +getnext: ;AN000; + LODSB ;AN000;;FO. get char + OR AL,AL ;AN000;;FO. is it null + JZ NO_Question ;AN000;;FO. yes + CMP AL,'?' ;AN000;;FO. is '?' + JNZ getnext ;AN000;;FO. no + STC ;AN000;;FO. +NO_Question: ;AN000; + return ;AN000;;FO. + +EndProc CHECK_QUESTION ;AN000; + +CODE ENDS + END diff --git a/v4.0/src/DOS/KSTRIN.ASM b/v4.0/src/DOS/KSTRIN.ASM new file mode 100644 index 0000000..1eeee39 --- /dev/null +++ b/v4.0/src/DOS/KSTRIN.ASM @@ -0,0 +1,690 @@ +; SCCSID = @(#)strin.asm 1.2 85/04/18 +; +; Revision history: +; A000 version 4.00 Jan. 1988 +; +Break + +; Inputs: +; DS:DX Point to an input buffer +; Function: +; Fill buffer from console input until CR +; Returns: +; None + + procedure $STD_CON_STRING_INPUT,NEAR ;System call 10 +ASSUME DS:NOTHING,ES:NOTHING + + MOV AX,SS + MOV ES,AX + MOV SI,DX + XOR CH,CH + LODSW + mov cs:Temp_Var,si ;AN000; ; 3/31/KK +; +; AL is the buffer length +; AH is the template length +; + OR AL,AL + retz ;Buffer is 0 length!!? + MOV BL,AH ;Init template counter + MOV BH,CH ;Init template counter + ; + ; BL is the number of bytes in the template + ; + CMP AL,BL + JBE NOEDIT ;If length of buffer inconsistent with contents + CMP BYTE PTR [BX+SI],c_CR + JZ EDITON ;If CR correctly placed EDIT is OK +; +; The number of chars in the template is >= the number of chars in buffer or +; there is no CR at the end of the template. This is an inconsistant state +; of affairs. Pretend that the template was empty: +; +NOEDIT: + MOV BL,CH ;Reset buffer +EDITON: + MOV DL,AL + DEC DX ;DL is # of bytes we can put in the buffer +; +; Top level. We begin to read a line in. +; +NEWLIN: + MOV AL,[CARPOS] + MOV [STARTPOS],AL ;Remember position in raw buffer + PUSH SI + MOV DI,OFFSET DOSGROUP:INBUF ;Build the new line here + MOV [INSMODE],CH ;Insert mode off + MOV BH,CH ;No chars from template yet + MOV DH,CH ;No chars to new line yet + call IntCNE0 ;AN000; Get first char 2/17/KK + jz SavCh ;AN000; if ZF set then interim character 2/17/KK + CMP AL,c_LF ;Linefeed + JNZ GOTCH ;Filter out LF so < works +; +; This is the main loop of reading in a character and processing it. +; +; BH is the index of the next byte in the template +; BL is the length of the template +; DH is the number of bytes in the buffer +; DL is the length of the buffer +; +entry GETCH + call IntCNE0 ;AN000;; 2/17/KK + jz SavCh ;AN000;; if ZF set then interim character 2/17/KK +GOTCH: +; +; ^F ignored in case BIOS did not flush the input queue. +; + CMP AL,"F"-"@" + JZ GETCH +; +; If the leading char is the function-key lead byte +; + CMP AL,[ESCCHAR] + JNZ ARM03 ;AN000;; 2/17/KK + Jmp ESCC ;AN000;; 2/17/KK +ARM03: ;AN000;; 2/17/KK +; +; Rubout and ^H are both destructive backspaces. +; + CMP AL,c_DEL + JZ BACKSPJ0 ;AN000; 2/17/KK + CMP AL,c_BS + JNZ ARM04 ;AN000;; 2/17/KK +BACKSPJ0: ;AN000;; 2/17/KK + Jmp BACKSPJ ;AN000;; 2/17/KK +ARM04: ;AN000;; 2/17/KK +; +; ^W deletes backward once and then backs up until a letter is before the +; cursor +; + CMP AL,"W" - "@" +; The removal of the comment characters before the jump statement will +; cause ^W to backup a word. +;*** JZ WordDel + NOP + NOP + CMP AL,"U" - "@" +; The removal of the comment characters before the jump statement will +; cause ^U to clear a line. +;*** JZ LineDel + NOP + NOP + +; +; CR terminates the line. +; + CMP AL,c_CR + JNZ ARM01 ;AN000;; 2/17/KK + Jmp ENDLIN ;AN000;; 2/17/KK +ARM01: ;AN000;; 2/17/KK +; +; LF goes to a new line and keeps on reading. +; + CMP AL,c_LF + JNZ ARM00 ;AN000;; 2/17/KK + Jmp PHYCRLF ;AN000;; 2/17/KK +ARM00: ;AN000;; 2/17/KK +; +; ^X (or ESC) deletes the line and starts over +; + CMP AL,[CANCHAR] + JNZ SAVCH ;AN000;; 2/13/KK + JMP KILNEW ;AN000;; 2/13/KK +InterLoop: ;AN000;; 2/17/KK + call IntCNE0 ;AN000;; Get another interim character 2/17/KK +; +; Otherwise, we save the input character. +; +SAVCH: + pushf ;AN000; 2/17/KK + CMP DH,DL + JAE BUFFUL ; buffer is full. +;----------------------------- Start of DBCS 2/13/KK + + invoke TESTKANJ ;AN000; + JZ ISNORM ;AN000; + INC DH ;AN000; + CMP DH,DL ;AN000; + JB GOTROOM ;AN000; + DEC DH ;AN000;; No room for second byte + call IntCNE0 ;AN000;; Get second byte + JMP SHORT BUFFUL ;AN000; + ;AN000; +GOTROOM: ;AN000; + STOSB ;AN000;; Store first byte + popf ;AN000; + call outchax ;AN000; + call IntCNE0 ;AN000;; Get second byte + pushf ;AN000; + STOSB ;AN000;; Store second byte + INC DH ;AN000; + popf ;AN000; + call outchax ;AN000; + jnz ContIn1 ;AN000;; interim character? + call InterCheck ;AN000; + call InterCheck ;AN000; + jmp short InterLoop ;AN000;; not interim skip another check + +ISNORM: +;----------------------------- End of DBCS 2/13/KK + STOSB ;AN000; + INC DH ;AN000;; increment count in buffer. + popf ;AN000;; 2/17/KK + invoke BUFOUTx ;AN000;; Print control chars nicely 2/17/KK + jnz ContIn1 ;AN000;; 2/17/KK + call InterCheck ;AN000;; 2/17/KK + jmp short InterLoop ;AN000;; 2/17/KK +CONTIN1: ;AN000;; 2/13/KK +;;;CONTIN: ;AN000;; 2/13/KK + CMP BYTE PTR [INSMODE],0 + JNZ GETCH0 ; insertmode => don't advance template + CMP BH,BL + JAE GETCH0 ; no more characters in template + INC SI ; Skip to next char in template + INC BH ; remember position in template + + PUSH AX ; + MOV AL,BYTE PTR [SI-1] ;AN000;; 2/13/KK + invoke TESTKANJ ;AN000;; 2/13/KK + POP AX ;AN000;; 2/13/KK + JZ GETCH0 ;AN000;; Wasn't a dual byte 2/13/KK + INC SI ;AN000;; Was a dual byte, 2/13/KK + INC BH ;AN000;; skip one more 2/13/KK +GETCH0: ;AN000;; 2/17/KK + JMP GETCH ;AN000;; 2/17/KK + +BACKSPJ: JMP SHORT BACKSP + +BUFFUL: + popf ;AN000;; 2/17/KK + MOV AL,7 ;AN000;; Bell to signal full buffer + invoke OUTT + JMP GETCH +; 2/17/KK +; Reduce character count, reduce pointer 2/17/KK +; 2/17/KK +InterCheck: ;AN000;; 2/17/KK + dec dh ;AN000;; adjust count 2/17/KK + dec di ;AN000;; adjust buffer pointer 2/17/KK + ret ;AN000;; 2/17/KK + +ESCC: + transfer OEMFunctionKey ; let the OEM's handle the key dispatch + +ENDLIN: + STOSB ; Put the CR in the buffer + invoke OUTT ; Echo it + POP DI ; Get start of user buffer + MOV [DI-1],DH ; Tell user how many bytes + INC DH ; DH is length including CR +COPYNEW: + SaveReg + RestoreReg ; XCHG ES,DS + MOV SI,OFFSET DOSGROUP:INBUF + MOV CL,DH ; set up count + REP MOVSB ; Copy final line to user buffer + return +; +; Output a CRLF to the user screen and do NOT store it into the buffer +; +PHYCRLF: + invoke CRLF + JMP GETCH + +; +; Delete the previous line +; +LineDel: + OR DH,DH + JNZ bridge00 ;AN000;; 2/13/KK + JMP GetCh ;AN000;; 2/13/KK +bridge00: ;AN000;; 2/13/KK + Call BackSpace + JMP LineDel + +; +; delete the previous word. +; +WordDel: +WordLoop: + Call BackSpace ; backspace the one spot + OR DH,DH + JZ GetChJ + MOV AL,ES:[DI-1] + cmp al,'0' + jb GetChj + cmp al,'9' + jbe WordLoop + OR AL,20h + CMP AL,'a' + JB GetChJ + CMP AL,'z' + JBE WordLoop +GetChJ: + JMP GetCh +; +; The user wants to throw away what he's typed in and wants to start over. We +; print the backslash and then go to the next line and tab to the correct spot +; to begin the buffered input. +; + entry KILNEW + MOV AL,"\" + invoke OUTT ;Print the CANCEL indicator + POP SI ;Remember start of edit buffer +PUTNEW: + invoke CRLF ;Go to next line on screen + MOV AL,[STARTPOS] + invoke TAB ;Tab over + JMP NEWLIN ;Start over again + + +; +; Destructively back up one character position +; +entry BackSp + Call BackSpace + JMP GetCh + +BackSpace: + OR DH,DH + JZ OLDBAK ;No chars in line, do nothing to line + CALL BACKUP ;Do the backup + MOV AL,ES:[DI] ;Get the deleted char + invoke TESTKANJ ;AN000;2/13/KK + JNZ OLDBAK ;AN000; Was a dual byte, done 2/13/KK + CMP AL," " + JAE OLDBAK ;Was a normal char + CMP AL,c_HT + JZ BAKTAB ;Was a tab, fix up users display +;; 9/27/86 fix for ctrl-U backspace + CMP AL,"U"-"@" ; ctrl-U is a section symbol not ^U + JZ OLDBAK + CMP AL,"T"-"@" ; ctrl-T is a paragraphs symbol not ^T + JZ OLDBAK +;; 9/27/86 fix for ctrl-U backspace + CALL BACKMES ;Was a control char, zap the '^' +OLDBAK: + CMP BYTE PTR [INSMODE],0 + retnz ;In insert mode, done + OR BH,BH + retz ;Not advanced in template, stay where we are + DEC BH ;Go back in template + DEC SI +;-------------------------- Start of DBCS 2/13/KK + OR BH,BH ;AN000; + retz ;AN000;; If we deleted one char and it was the only + ;AN000;; one, could not have dual byte +;;;; POP AX ;AN000;; Get start of template +;;;; PUSH AX ;AN000;; Put it back on stack + mov ax,cs:Temp_Var ;AN000;; 3/31/KK + XCHG AX,SI ;AN000; +LOOKDUAL: ;AN000; + CMP SI,AX ;AN000; + JAE ATLOC ;AN000; + PUSH AX ;AN000; + MOV AL,BYTE PTR [SI];AN000; + invoke TESTKANJ ;AN000; + POP AX ;AN000; + JZ ONEINC ;AN000; + INC SI ;AN000; +ONEINC: ;AN000; + INC SI ;AN000; + JMP SHORT LOOKDUAL ;AN000; + ;AN000; +ATLOC: ;AN000; + retz ;AN000;; Correctly pointing to start of single byte + DEC AX ;AN000;; Go back one more to correctly point at start + DEC BH ;AN000; ; of dual byte + MOV SI,AX ;AN000; + return ;AN000; +;-------------------------- End of DBCS 2/13/KK + +BAKTAB: + PUSH DI + DEC DI ;Back up one char + STD ;Go backward + MOV CL,DH ;Number of chars currently in line + MOV AL," " + PUSH BX + MOV BL,7 ;Max + JCXZ FIGTAB ;At start, do nothing +FNDPOS: + SCASB ;Look back + JNA CHKCNT + CMP BYTE PTR ES:[DI+1],9 + JZ HAVTAB ;Found a tab + DEC BL ;Back one char if non tab control char +CHKCNT: + LOOP FNDPOS +FIGTAB: + SUB BL,[STARTPOS] +HAVTAB: + SUB BL,DH + ADD CL,BL + AND CL,7 ;CX has correct number to erase + CLD ;Back to normal + POP BX + POP DI + JZ OLDBAK ;Nothing to erase +TABBAK: + invoke BACKMES + LOOP TABBAK ;Erase correct number of chars + JMP SHORT OLDBAK + +BACKUP: + DEC DH ;Back up in line + DEC DI +;-------------------------Start of DBCS 2/13/KK + OR DH,DH ;AN000; + JZ BACKMES ;AN000;; If deleted one and got only, no dual + MOV AX,DI ;AN000; + MOV DI,OFFSET DOSGROUP:INBUF;AN000; +LOOKDUAL2: ;AN000; + CMP DI,AX ;AN000; + JAE ATLOC2 ;AN000; + PUSH AX ;AN000; + MOV AL,BYTE PTR ES:[DI] ;AN000; + invoke TESTKANJ ;AN000; + POP AX ;AN000; + JZ ONEINC2 ;AN000; + INC DI ;AN000; +ONEINC2: ;AN000; + INC DI ;AN000; + JMP SHORT LOOKDUAL2 ;AN000; + ;AN000; +ATLOC2: ;AN000; + JE BACKMES ;AN000;; Correctly deleted single byte + DEC AX ;AN000; Go back one more to correctly delete dual byte + DEC DH ;AN000; + MOV DI,AX ;AN000; + CALL BACKMES ;AN000; +;---------------------------End of DBCS 2/13/KK +BACKMES: + MOV AL,c_BS ;Backspace + invoke OUTT + MOV AL," " ;Erase + invoke OUTT + MOV AL,c_BS ;Backspace + JMP OUTT ;Done + +;User really wants an ESC character in his line + entry TwoEsc + MOV AL,[ESCCHAR] + JMP SAVCH + +;Copy the rest of the template + entry COPYLIN + MOV CL,BL ;Total size of template + SUB CL,BH ;Minus position in template, is number to move + JMP SHORT COPYEACH + + entry CopyStr + invoke FINDOLD ;Find the char + JMP SHORT COPYEACH ;Copy up to it + +;Copy one char from template to line + entry COPYONE + MOV CX,1 ;AN000;; 2/13/KK + MOV AL,[SI] ;AN000;; get char 2/13/KK + invoke TestKanj ;AN000;; is it kanji? 2/13/KK + JZ CopyEach ;AN000;; no, go do copy2/13/KK + INC CX ;AN000;; do 2 byte copy2/13/KK + +;Copy CX chars from template to line +COPYEACH: + MOV BYTE PTR [INSMODE],0 ;All copies turn off insert mode + CMP DH,DL + JZ GETCH2 ;At end of line, can't do anything + CMP BH,BL + JZ GETCH2 ;At end of template, can't do anything + LODSB + STOSB +;----------------------------- Start of DBCS 2/13/KK + INC BH ;AN000;; Ahead in template + INC DH ;AN000;; Ahead in line + CALL TestKanj ;AN000;; 2 byte character? + JZ CopyLoop ;AN000;; no, go copy next + CMP DH,DL ;AN000;; over boundary? + JNZ CopyBoth ;AN000;; no, move both + DEC BH ;AN000;; yes, backup template + DEC DH ;AN000;; back up line + DEC SI ;AN000;; patch (from Dohhaku) + DEC DI ;AN000;; remember to backup after previous move + JMP GetCh ;AN000;; go get next char + ;AN000; +CopyBoth: ;AN000; + invoke BUFOUT ;AN000;; output the first byte + LODSB ;AN000;; get the second + STOSB ;AN000;; move the second + INC BH ;AN000;; bump template + INC DH ;AN000;; bump line + DEC CX ;AN000;; dump byte count +CopyLoop: ;AN000; + invoke BUFOUT ;AN000; + LOOP COPYEACH ;AN000; +;;;;; invoke BUFOUT +;;;;; INC BH ;Ahead in template +;;;;; INC DH ;Ahead in line +;;;;; LOOP COPYEACH +;----------------------------- End of DBCS 2/13/KK +GETCH2: + JMP GETCH + +;Skip one char in template + entry SKIPONE + CMP BH,BL + JZ GETCH2 ;At end of template + INC BH ;Ahead in template + INC SI + PUSH AX ;AN000;; 2/13/KK + MOV AL,BYTE PTR [SI-1] ;AN000;; 2/13/KK + invoke TESTKANJ ;AN000;; 2/13/KK + POP AX ;AN000;; 2/13/KK + JZ GETCH2 ;AN000;; 2/13/KK + INC BH ;AN000;; 2/13/KK + INC SI ;AN000;; 2/13/KK + JMP GETCH + + entry SKIPSTR + invoke FINDOLD ;Find out how far to go + ADD SI,CX ;Go there + ADD BH,CL + JMP GETCH + +;Get the next user char, and look ahead in template for a match +;CX indicates how many chars to skip to get there on output +;NOTE: WARNING: If the operation cannot be done, the return +; address is popped off and a jump to GETCH is taken. +; Make sure nothing extra on stack when this routine +; is called!!! (no PUSHes before calling it). + +TABLE SEGMENT ;AN000;; 2/17/KK +Public KISTR001S,KISTR001E ;AN000;; 2/17/KK +KISTR001S label byte ;AN000;; 2/17/KK +LOOKSIZ DB 0 ;AN000;; 0 if byte, NZ if word 2/17/KK +KISTR001E label byte ;AN000;; 2/17/KK +TABLE ENDS ;AN000;; 2/17/KK + +FINDOLD: + MOV [LOOKSIZ],0 ;AN000;; Initialize to byte 2/13/KK + call IntCNE1 ;AN000;; 2/17/KK + CMP AL,[ESCCHAR] ;AN000;; did he type a function key? +;;;;; JNZ FindSetup ;AN000;; no, set up for scan 2/13/KK + JNZ TryKanj ;AN000;; no, continue testing 2/13/KK + call IntCNE1 ;AN000;; 2/17/KK + JMP NotFnd ; go try again +;;;;;;;FindSetup: ;AN000;; 2/13/KK +TryKanj: ;AN000;; 2/13/KK + invoke TESTKANJ ;AN000;; 2/13/KK + JZ GOTLSIZ ;AN000;; 2/13/KK + INC [LOOKSIZ] ;AN000;; Gonna look for a word 2/13/KK + PUSH AX ;AN000;; Save first byte 2/13/KK + call IntCNE1 ;AN000;; 2/17/KK + POP CX ;AN000;; 2/13/KK + MOV AH,AL ;AN000;; 2/13/KK + MOV AL,CL ;AN000;; AX is dual byte sequence to look for + XOR CX,CX ;AN000;; Re-zero CH 2/13/KK +GOTLSIZ: + MOV CL,BL + SUB CL,BH ;CX is number of chars to end of template + JZ NOTFND ;At end of template + DEC CX ;Cannot point past end, limit search + JZ NOTFND ;If only one char in template, forget it + PUSH AX ;AN000;; 2/13/KK + MOV AL,BYTE PTR [SI] ;AN000;; 2/13/KK + invoke TESTKANJ ;AN000;; 2/13/KK + POP AX ;AN000;; 2/13/KK + JZ NOTDUAL5 ;AN000;; 2/13/KK + DEC CX ;AN000;; And one more besides 2/13/KK + JZ NOTFND ;AN000;; If only one char in template, forget it +NOTDUAL5: ;AN000;; 2/13/KK + PUSH ES + PUSH DS + POP ES + PUSH DI + MOV DI,SI ;Template to ES:DI +;;;; INC DI 2/13/KK +;;;; REPNE SCASB ;Look 2/13/KK +;--------------------- Start of DBCS 2/13/KK + PUSH AX ;AN000; + MOV AL,BYTE PTR ES:[DI] ;AN000; + invoke TESTKANJ ;AN000; + POP AX ;AN000; + JZ ONEINC5 ;AN000; + INC DI ;AN000;; We will skip at least something +ONEINC5: ;AN000; + INC DI ;AN000; + CMP [LOOKSIZ],0 ;AN000; + JNZ LOOKWORD ;AN000; +LOOKBYTE: ;AN000; + PUSH AX ;AN000; + MOV AL,BYTE PTR ES:[DI] ;AN000; + invoke TESTKANJ ;AN000; + POP AX ;AN000; + JZ TESTITB ;AN000; + INC DI ;AN000; + INC DI ;AN000; + DEC CX ;AN000; + LOOP LOOKBYTE ;AN000; + JMP SHORT ATNOTFND ;AN000; + ;AN000; +TESTITB: ;AN000; + DEC CX ;AN000; + CMP AL,ES:[DI] ;AN000; + JZ ATSPOT ;AN000; + INC DI ;AN000; + INC CX ;AN000;; Counter next instruction + LOOP LOOKBYTE ;AN000; +ATNOTFND: ;AN000; + XOR AL,AL ;AN000; + INC AL ;AN000;; Set NZ +ATSPOT: ; 2/13/K;AN000;K +;--------------------- End of DBCS 2/13/KK + POP DI + POP ES + JNZ NOTFND ;Didn't find the char + NOT CL ;Turn how far to go into how far we went + ADD CL,BL ;Add size of template + SUB CL,BH ;Subtract current pos, result distance to skip + return + +NOTFND: + POP BP ;Chuck return address + JMP GETCH +;------------------------- Start of DBCS 2/13/KK +LOOKWORD: ;AN000; + PUSH AX ;AN000; + MOV AL,BYTE PTR ES:[DI] ;AN000; + invoke TESTKANJ ;AN000; + POP AX ;AN000; + JNZ TESTITW ;AN000; + INC DI ;AN000; + LOOP LOOKWORD ;AN000; + JMP SHORT ATNOTFND ;AN000; + ;AN000; +TESTITW: ;AN000; + DEC CX ;AN000; + CMP AX,ES:[DI] ;AN000; + JZ ATSPOT ;AN000; + INC DI ;AN000; + INC DI ;AN000; + LOOP LOOKWORD ;AN000; ; Performs second DEC of CX + JMP SHORT ATNOTFND ;AN000; +;------------------------- End of DBCS 2/13/KK + +entry REEDIT + MOV AL,"@" ;Output re-edit character + invoke OUTT + POP DI + PUSH DI + PUSH ES + PUSH DS + invoke COPYNEW ;Copy current line into template + POP DS + POP ES + POP SI + MOV BL,DH ;Size of line is new size template + JMP PUTNEW ;Start over again + + entry EXITINS + entry ENTERINS + NOT BYTE PTR [INSMODE] + JMP GETCH + +;Put a real live ^Z in the buffer (embedded) + entry CTRLZ + MOV AL,"Z"-"@" + JMP SAVCH + +;Output a CRLF + entry CRLF + MOV AL,c_CR + invoke OUTT + MOV AL,c_LF + JMP OUTT + +EndProc $STD_CON_STRING_INPUT + +;-------------- Start of DBCS 2/17/KK +PUBLIC IntCNE0 ;AN000; +procedure IntCNE0,near ;AN000; + push word ptr [InterCon] ;AN000; + mov [InterCon],01 ;AN000; +get_com: ;AN000; + invoke INTER_CON_INPUT_NO_ECHO ;AN000;; get a byte character + pop word ptr [InterCon] ;AN000; + ret ;AN000; +IntCNE0 endp ;AN000; + ;AN000; +procedure IntCNE1,near ;AN000; + push word ptr [InterCon] ;AN000; + mov [InterCon],00 ;AN000; + jmp short get_com ;AN000; +IntCNE1 endp ;AN000; + ;AN000; + procedure outchax,near ;AN000; + pushf ;AN000; + mov [SaveCurFlg],0 ;AN000; + jnz sj1 ;AN000; + mov [SaveCurFlg],1 ;AN000; +sj1: ;AN000; + CALL OUTCHA ;AN000; + mov [SaveCurFlg],0 ;AN000; + popf ;AN000; + ret ;AN000; +outchax endp ;AN000; + ;AN000; + procedure bufoutx,near ;AN000; + pushf ;AN000; + mov [SaveCurFlg],0 ;AN000; + jnz sj2 ;AN000; + mov [SaveCurFlg],1 ;AN000; +sj2: ;AN000; + invoke BUFOUT ;AN000; + mov [SaveCurFlg],0 ;AN000; + popf ;AN000; + ret ;AN000; +bufoutx endp ;AN000; +;-------------- End of DBCS 2/17/KK diff --git a/v4.0/src/DOS/LOCK.ASM b/v4.0/src/DOS/LOCK.ASM new file mode 100644 index 0000000..2089882 --- /dev/null +++ b/v4.0/src/DOS/LOCK.ASM @@ -0,0 +1,372 @@ +; SCCSID = @(#)lock.asm 1.1 85/04/10 +TITLE LOCK ROUTINES - Routines for file locking +NAME LOCK + +; +; LOCK_CHECK +; LOCK_VIOLATION +; $LockOper +; +; Revision history: +; A000 version 4.00 Jan. 1988 +; +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xlist +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +include lock.inc ;AN000; +.cref +.list + +AsmVars + +Installed = TRUE + + i_need THISSFT,DWORD + i_need THISDPB,DWORD + i_need EXTERR,WORD + i_need ALLOWED,BYTE + i_need RetryCount,WORD + I_need fShare,BYTE + I_Need EXTERR_LOCUS,BYTE ; Extended Error Locus + i_need JShare,DWORD + i_need Lock_Buffer,DWORD ;AN000; DOS 4.00 + i_need Temp_Var,WORD ;AN000; DOS 4.00 + +BREAK <$LockOper - Lock Calls> + +; +; Assembler usage: +; MOV BX, Handle (DOS 3.3) +; MOV CX, OffsetHigh +; MOV DX, OffsetLow +; MOV SI, LengthHigh +; MOV DI, LengthLow +; MOV AH, LockOper +; MOV AL, Request +; INT 21h +; +; Error returns: +; AX = error_invalid_handle +; = error_invalid_function +; = error_lock_violation +; +; Assembler usage: +; MOV AX, 5C?? (DOS 4.00) +; +; 0? lock all +; 8? lock write +; ?2 lock multiple +; ?3 unlock multiple +; ?4 lock/read +; ?5 write/unlock +; ?6 add (lseek EOF/lock/write/unlock) +; MOV BX, Handle +; MOV CX, count or size +; LDS DX, buffer +; INT 21h +; +; Error returns: +; AX = error_invalid_handle +; = error_invalid_function +; = error_lock_violation + + procedure $LockOper,NEAR +ASSUME DS:NOTHING,ES:NOTHING +; MOV BP,AX ;MS. BP=AX ;AN000; +; AND BP,7FH ;MS. clear bit 7 ;AN000; +; CMP BP,Lock_add ;MS. supported function ? ;AN000; +; JA lock_bad_func ;MS. no, ;AN000; + + CMP AL,1 ;AN000;;MS. no, + JA lock_bad_func ;AN000;;MS. no, + + PUSH DI ; Save LengthLow + invoke SFFromHandle ; ES:DI -> SFT + JNC lock_do ; have valid handle + POP DI ; Clean stack + error error_invalid_handle +lock_bad_func: + MOV EXTERR_LOCUS,errLoc_Unk ; Extended Error Locus + error error_invalid_function + +; Align_buffer call has been deleted, since it corrupts the DTA (6/5/88) P5013 + +lock_do: +; PUSH AX ;AN000;;MS. save ax +; PUSH BX ;AN000;;MS. save handle +; MOV [Temp_Var],DX ;AN000;;MS. save DX +; invoke Align_Buffer ;AN000;;MS. align ds:dx and set DMAADD +; POP BX ;AN000;;MS. restore handle +; POP AX ;AN000;;MS. save ax + ;AN000; +; CMP BP,Unlock_all ;AN000;;MS. old function 0 or 1 ? +; JA chk_lock_mul ;AN000;;MS. no, new function +; TEST AL,80H ;AN000;;MS. 80H bit on ? +; JZ old_33 ;AN000;;MS. no, old DOS 3.3 interface +; MOV CX,1 ;AN000;;MS. adjust for new interface +; ADD BP,2 ;AN000;;MS. +; JMP SHORT chk_lock_mul ;AN000;;MS. +old_33: + MOV BX,AX ;AN000;;MS. save AX + ;AN000; +;; MOV DX,[Temp_Var] ;AN000;;MS. retore DX (P5013) 6/5/88 + + MOV BP, OFFSET DOSGROUP:Lock_Buffer ;AN000;;MS. get DOS LOCK buffer + MOV WORD PTR [BP.Lock_position],DX ;AN000;;MS. set low offset + MOV WORD PTR [BP.Lock_position+2],CX;AN000;;MS. set high offset + POP CX ;AN000;;MS. get low length + MOV WORD PTR [BP.Lock_length],CX ;AN000;;MS. set low length + MOV WORD PTR [BP.Lock_length+2],SI ;AN000;;MS. set high length + MOV CX,1 ;AN000;;MS. one range + PUSH CS ;AN000;;MS. + POP DS ;AN000;;MS. DS:DX points to + MOV DX,BP ;AN000;;MS. Lock_Buffer + TEST AL,Unlock_all ;AN000;;MS. function 1 + JNZ DOS_Unlock ;AN000;;MS. yes + JMP DOS_Lock ;AN000;;MS. function 0 +;;chk_lock_mul: ;AN000; +; POP SI ;AN000;;MS. pop low length +; TEST ES:[DI.sf_flags],sf_isnet ;AN000;;MS. net handle? +; JZ LOCAL_DOS_LOCK ;AN000;;MS. no +; invoke OWN_SHARE ;AN000;;MS. IFS owns share ? +; JNZ LOCAL_DOS_LOCK ;AN000;;MS. no +; MOV BX,AX ;AN000;;MS. BX=AX +; CallInstall NET_XLock,multNet,10 ;AN000;;MS. issue Net Extended Lock +; MOV [Temp_Var],CX ;AN000;;MS. cx= retuened from IFS +; JMP ValChk ;AN000;;MS. check return +;LOCAL_DOS_LOCK: ;AN000; +; CMP BP,Lock_mul_range ;AN000;;MS. lock mul range? +; JNZ unmul ;AN000;;MS. lock mul range? +; JMP LOCAL_LOCK ;AN000;;MS. yes +;unmul: +; CMP BP,Unlock_mul_range ;AN000;;MS. unlock mul range? +; JZ LOCAL_UNLOCK ;AN000;;MS. yes +; CMP BP,Lock_read ;AN000;;MS. lock read? +; JNZ chk_write_unlock ;AN000;;MS. no +; CALL Set_Lock_Buffer ;AN000;;MS. set DOS lock buffer +; CALL Set_Lock ;AN000;;MS. set the lock +; JC lockerror ;AN000;;MS. error +; invoke $READ ;AN000;;MS. do read +; JC lockerror ;AN000;;MS. error +;lockend: ;AN000; +; transfer SYS_RET_OK ;AN000;;MS. return +;chk_write_unlock: ;AN000; +; CMP BP,Write_unlock ;AN000;;MS. write unlock ? +; JNZ Lock_addf ;AN000;;MS. no +; CALL Set_Lock_Buffer ;AN000;;MS. set DOS lock buffer +;WriteUnlock: ;AN000; +; PUSH AX ;AN000;;MS. save AX for unlock +; invoke $WRITE ;AN000;;MS. do write +; MOV [Temp_Var],AX ;AN000;;MS. save number of bytes writ +; POP AX ;AN000;;MS. restore AX +; JC lockerror ;AN000;;MS. error +; MOV CX,1 ;AN000;;MS. one range unlock +; PUSH CS ;AN000;;MS. +; POP DS ;AN000;;MS. DS:DX points to +; MOV DX,OFFSET DOSGROUP:Lock_Buffer ;AN000;;MS. Lock_BUffer +; JMP LOCAL_UNLOCK ;AN000;;MS. do unlock +;Lock_addf: ;AN000; +; MOV SI,WORD PTR ES:[DI.SF_Size] ;AN000;;MS. must be lock add +; MOV WORD PTR ES:[DI.SF_Position],SI ;AN000;;MS. set file position to +; MOV SI,WORD PTR ES:[DI.SF_Size+2] ;AN000;;MS. EOF +; MOV WORD PTR ES:[DI.SF_Position+2],SI;AN000;;MS. +; CALL Set_Lock_Buffer ;AN000;;MS. set DOS lock buffer +; CALL Set_Lock ;AN000;;MS. set the lock +; JC lockerror ;AN000;;MS. error +; JMP WriteUnlock ;AN000;;MS. do write unlock + ;AN000;;MS. +DOS_Unlock: + TEST ES:[DI.sf_flags],sf_isnet + JZ LOCAL_UNLOCK +;; invoke OWN_SHARE ;AN000;;MS. IFS owns share ? +;; JNZ LOCAL_UNLOCK ;AN000;;MS. no + + CallInstall Net_Xlock,multNet,10 + JMP SHORT ValChk +LOCAL_UNLOCK: +if installed + Call JShare + 7 * 4 +else + Call clr_block +endif +ValChk: + JNC Lock_OK +lockerror: + transfer SYS_RET_ERR +Lock_OK: + MOV AX,[Temp_VAR] ;AN000;;MS. AX= number of bytes + transfer SYS_Ret_OK +DOS_Lock: + TEST ES:[DI.sf_flags],sf_isnet + JZ LOCAL_LOCK +;; invoke OWN_SHARE ;AN000;;MS. IFS owns share ? +;; JNZ LOCAL_LOCK ;AN000;;MS. no + CallInstall NET_XLock,multNet,10 + JMP ValChk +LOCAL_LOCK: +if installed + Call JShare + 6 * 4 +else + Call Set_Block +endif + JMP ValChk + +EndProc $LockOper + +BREAK + +; Input: +; BP = Lock_Buffer addr +; CX = lock length +; Function: +; set the lock +; Output: +; carry clear ,Lock is set +; DS:DX = addr of +; carry set Lock is not set +; DS,DX,CX preserved + +; procedure Set_Lock,NEAR ;AN000; +;ASSUME DS:NOTHING,ES:NOTHING ;AN000; + ;AN000; +; PUSH DS ;MS. save regs ;AN000; +; PUSH DX ;MS. ;AN000; +; PUSH CX ;MS. ;AN000; +; ;AN000; +; PUSH CS ;MS. ;AN000; +; POP DS ;MS. DS:DX poits to Lock_Buffer ;AN000; +; MOV DX,BP ;MS. ;AN000; +; PUSH BX ;MS. save handle ;AN000; +; PUSH AX ;MS. save functions ;AN000; +; MOV CX,1 ;MS. set one lock ;AN000; +;if installed ;AN000; +; Call JShare + 6 * 4 ;MS. call share set block ;AN000; +;else ;AN000; +; Call Set_Block ;MS. ;AN000; +;endif ;AN000; +; POP AX ;MS. restore regs ;AN000; +; POP BX ;MS. ;AN000; +; POP CX ;MS. ;AN000; +; POP DX ;MS. ;AN000; +; POP DS ;MS. ;AN000; +; return ;MS. ;AN000; +; ;AN000; +;EndProc Set_Lock ;AN000; + +BREAK + +; Input: +; ES:DI = addr of SFT +; CX = lock length +; Function: +; set up the lock buffer +; Output: +; Lock_Buffer is filled with position and lock length +; BP = Lock_Buffer addr +; + +; procedure Set_Lock_Buffer,NEAR +;ASSUME DS:NOTHING,ES:NOTHING +; +; MOV BP, OFFSET DOSGROUP:Lock_Buffer ;MS. move file position ;AN000; +; MOV SI,WORD PTR ES:[DI.sf_position] ;MS. to DOS lock_buffer ;AN000; +; MOV WORD PTR [BP.Lock_position],SI ;MS. ;AN000; +; MOV SI,WORD PTR ES:[DI.sf_position+2] ;MS. ;AN000; +; MOV WORD PTR [BP.Lock_position+2],SI ;MS. ;AN000; +; MOV WORD PTR [BP.Lock_length],CX ;MS. move cx to lock_buffer ;AN000; +; MOV WORD PTR [BP.Lock_length+2],0 ;MS. ;AN000; +; return ;MS. ;AN000; +; +;EndProc Set_Lock_Buffer + +; Inputs: +; Outputs of SETUP +; [USER_ID] Set +; [PROC_ID] Set +; Function: +; Check for lock violations on local I/O +; Retries are attempted with sleeps in between +; Outputs: +; Carry clear +; Operation is OK +; Carry set +; A lock violation detected +; Outputs of SETUP preserved + + procedure LOCK_CHECK,NEAR + DOSAssume CS,,"Lock_Check" + ASSUME ES:NOTHING + + MOV BX,RetryCount ; Number retries +LockRetry: + SaveReg ; MS. save regs ;AN000; +if installed + call JShare + 8 * 4 +else + Call chk_block +endif + RestoreReg ; MS. restrore regs ;AN000; + retnc ; There are no locks + Invoke Idle ; wait a while + DEC BX ; remember a retry + JNZ LockRetry ; more retries left... + STC + return +EndProc LOCK_CHECK + +; Inputs: +; [THISDPB] set +; [READOP] indicates whether error on read or write +; Function: +; Handle Lock violation on compatibility (FCB) mode SFTs +; Outputs: +; Carry set if user says FAIL, causes error_lock_violation +; Carry clear if user wants a retry +; +; DS, ES, DI, CX preserved, others destroyed + + procedure LOCK_VIOLATION,NEAR + DOSAssume CS,,"Lock_Violation" + ASSUME ES:NOTHING + + PUSH DS + PUSH ES + PUSH DI + PUSH CX + MOV AX,error_lock_violation + MOV [ALLOWED],allowed_FAIL + allowed_RETRY + LES BP,[THISDPB] + MOV DI,1 ; Fake some registers + MOV CX,DI + MOV DX,ES:[BP.dpb_first_sector] + invoke HARDERR + POP CX + POP DI + POP ES + POP DS + CMP AL,1 + retz ; 1 = retry, carry clear + STC + return + +EndProc LOCK_VIOLATION + +IF INSTALLED +; +; do a retz to return error +; +Procedure CheckShare,NEAR + ASSUME CS:DOSGROUP,ES:NOTHING,DS:NOTHING,SS:NOTHING + CMP fShare,0 + return +EndProc CheckShare +ENDIF + +CODE ENDS + END diff --git a/v4.0/src/DOS/MACRO.ASM b/v4.0/src/DOS/MACRO.ASM new file mode 100644 index 0000000..dea0771 --- /dev/null +++ b/v4.0/src/DOS/MACRO.ASM @@ -0,0 +1,445 @@ +; SCCSID = @(#)macro.asm 1.2 85/07/11 +TITLE MACRO - Pathname and macro related internal routines +NAME MACRO +; +; $AssignOper written +; FIND_DPB written +; InitCDS written +; $UserOper written +; GetVisDrv written +; GetThisDrv written +; GetCDSFromDrv written +; +; Revision history: +; +; Created: MZ 4 April 1983 +; MZ 18 April 1983 Make TransFCB handle extended FCBs +; AR 2 June 1983 Define/Delete macro for NET redir. +; MZ 3 Nov 83 Fix InitCDS to reset length to 2 +; MZ 4 Nov 83 Fix NetAssign to use STRLEN only +; MZ 18 Nov 83 Rewrite string processing for subtree +; aliasing. +; +; MSDOS performs several types of name translation. First, we maintain for +; each valid drive letter the text of the current directory on that drive. +; For invalid drive letters, there is no current directory so we pretend to +; be at the root. A current directory is either the raw local directory +; (consisting of drive:\path) or a local network directory (consisting of +; \\machine\path. There is a limit on the point to which a .. is allowed. +; +; Given a path, MSDOS will transform this into a real from-the-root path +; without . or .. entries. Any component that is > 8.3 is truncated to +; this and all * are expanded into ?'s. +; +; The second part of name translation involves subtree aliasing. A list of +; subtree pairs is maintained by the external utility SUBST. The results of +; the previous 'canonicalization' are then examined to see if any of the +; subtree pairs is a prefix of the user path. If so, then this prefix is +; replaced with the other subtree in the pair. +; +; A third part involves mapping this "real" path into a "physical" path. A +; list of drive/subtree pairs are maintained by the external utility JOIN. +; The output of the previous translation is examined to see if any of the +; subtrees in this list are a prefix of the string. If so, then the prefix +; is replaced by the appropriate drive letter. In this manner, we can +; 'mount' one device under another. +; +; The final form of name translation involves the mapping of a user's +; logical drive number into the internal physical drive. This is +; accomplished by converting the drive number into letter:CON, performing +; the above translation and then converting the character back into a drive +; number. +; +; curdir_list STRUC +; curdir_text DB DIRSTRLEN DUP (?) ; text of assignment and curdir +; curdir_flags DW ? ; various flags +; curdir_devptr DD ? ; local pointer to DPB or net device +; curdir_ID DW ? ; cluster of current dir (net ID) +; DW ? +; curdir_end DW ? ; end of assignment +; curdir_list ENDS +; curdir_netID EQU DWORD PTR curdir_ID +; ;Flag word masks +; curdir_isnet EQU 1000000000000000B +; curdir_inuse EQU 0100000000000000B +; +; There are two main entry points: TransPath and TransFCB. TransPath will +; take a path and form the real text of the pathname with all . and .. +; removed. TransFCB will translate an FCB into a path and then invoke +; TransPath. +; +; Implementation note: CURDIR_End field points to the point in the text +; string where the user may back up to via .. It is the location of a +; separator character. For the root, it points at the leading /. For net +; assignments it points at the end (nul) of the initial assignment: +; A:/ \\foo\bar \\foo\bar\blech\bozo +; ^ ^ ^ +; A: -> d: /path/ path/ text +; +; A000 version 4.00 Jan. 1988 + +.xlist +; +; get the appropriate segment definitions +; +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGroup,CS:DOSGroup + +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +.cref +.list +.sall + +Installed = TRUE + + I_need ThisCDS,DWORD ; pointer to CDS used + I_need CDSAddr,DWORD ; pointer to CDS table + I_need CDSCount,BYTE ; number of CDS entries + I_need CurDrv,BYTE ; current macro assignment (old + ; current drive) + I_need NUMIO,BYTE ; Number of physical drives + I_need fSharing,BYTE ; TRUE => no redirection allowed + I_need DummyCDS,80h ; buffer for dummy cds + I_need DIFFNAM,BYTE ; flag for MyName being set + I_need MYNAME,16 ; machine name + I_need MYNUM,WORD ; machine number + I_need DPBHEAD,DWORD ; beginning of DPB chain + I_need EXTERR_LOCUS,BYTE ; Extended Error Locus + I_need DrvErr,BYTE ; drive error + +BREAK <$AssignOper -- Set up a Macro> + +; Inputs: +; AL = 00 get assign mode (ReturnMode) +; AL = 01 set assign mode (SetMode) +; AL = 02 get attach list entry (GetAsgList) +; AL = 03 Define Macro (attch start) +; BL = Macro type +; = 0 alias +; = 1 file/device +; = 2 drive +; = 3 Char device -> network +; = 4 File device -> network +; DS:SI -> ASCIZ source name +; ES:DI -> ASCIZ destination name +; AL = 04 Cancel Macro +; DS:SI -> ASCIZ source name +; AL = 05 Modified get attach list entry +; AL = 06 Get ifsfunc item +; AL = 07 set in_use of a drive's CDS +; DL = drive number, 0=default 0=A,, +; AL = 08 reset in_use of a drive's CDS +; DL = drive number, 0=A, 1=B,,, +; Function: +; Do macro stuff +; Returns: +; Std Xenix style error return + + procedure $AssignOper,NEAR +ASSUME DS:NOTHING,ES:NOTHING + + CMP AL,7 ; set in_use ? ;AN000; + JNZ chk08 ; no ;AN000; +srinuse: ;AN000; + PUSH AX ; save al ;AN000; + MOV AL,DL ; AL= drive id ;AN000; + CALL GetCDSFromDrv ; ds:si -> cds ;AN000; + POP AX ; ;AN000; + JC baddrv ; bad drive ;AN000; + CMP WORD PTR [SI.curdir_devptr],0 ; dpb ptr =0 ? ;AN000; + JZ baddrv ; no ;AN000; + CMP AL,7 ; set ? ;AN000; + JNZ resetdrv ; no ;AN000; + OR [SI.curdir_flags],curdir_inuse ; set in_use ;AN000; + JMP SHORT okdone ; ;AN000; +resetdrv: ;AN000; + AND [SI.curdir_flags],NOT curdir_inuse ; reset in_use ;AN000; + JMP SHORT okdone ; ;AN000; +baddrv: ;AN000; + MOV AX,error_invalid_drive ; error ;AN000; + JMP SHORT ASS_ERR ; ;AN000; +chk08: ;AN000; + CMP AL,8 ; reset inuse ? ;AN000; + JZ srinuse ; yes ;AN000; + + IF NOT INSTALLED + transfer NET_ASSOPER + ELSE + PUSH AX + MOV AX,(multnet SHL 8) OR 30 + INT 2FH + POP BX ; Don't zap error code in AX + JC ASS_ERR +okdone: + transfer SYS_RET_OK + +ASS_ERR: + transfer SYS_RET_ERR + ENDIF + +EndProc $AssignOper + +Break + +; Inputs: AL has drive number A = 0 +; Outputs: Carry Set +; No DPB for this drive number +; Carry Clear +; DS:SI points to DPB for drive +; registers modified: DS,SI +Procedure FIND_DPB,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup + LDS SI,[DPBHEAD] +DPB_LOOP: + CMP SI,-1 + JZ NO_DPB + CMP AL,[SI.dpb_drive] + retz ; Carry clear + LDS SI,[SI.dpb_next_dpb] + JMP DPB_LOOP + +NO_DPB: + STC + return +EndProc FIND_DPB + +Break + +; Inputs: ThisCDS points to CDS +; AL has uppercase drive letter +; Outputs: ThisCDS is now empty +; ES:DI point to CDS +; Carry set if no DPB associated with drive +; registers modified: AH,ES,DI +Procedure InitCDS,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup + MOV AH,':' + PUSH AX + SUB AL,"A"-1 ; A = 1 + CMP [NUMIO],AL + POP AX + LES DI,[THISCDS] + MOV ES:[DI.curdir_flags],0 ; "free" CDS + JB RET_OK ; Drive does not map a physical drive + MOV WORD PTR ES:[DI.curdir_text],AX + PUSH AX + MOV AX,"\" + MOV WORD PTR ES:[DI.curdir_text+2],AX ; NUL terminate + POP AX + OR ES:[DI.curdir_flags],curdir_inuse + MOV ES:[DI.curdir_END],2 ; MZ 3 Nov 83 + MOV ES:[DI.curdir_ID],0 + MOV ES:[DI.curdir_ID+2],0 + PUSH AX + PUSH DS + PUSH SI + SUB AL,"A" ; A = 0 + invoke FIND_DPB + JC PRET ; OOOOPPPPPSSSS!!!! + MOV WORD PTR ES:[DI.curdir_devptr],SI + MOV WORD PTR ES:[DI.curdir_devptr+2],DS +PRET: + POP SI + POP DS + POP AX +RET_OK: return +EndProc InitCDS + +Break <$UserOper - get/set current user ID (for net)> + +; +; $UserOper - retrieve or initiate a user id string. MSDOS will only +; maintain this string and do no verifications. +; +; Inputs: AL has function type (0-get 1-set 2-printer-set 3-printer-get +; 4-printer-set-flags,5-printer-get-flags) +; DS:DX is user string pointer (calls 1,2) +; ES:DI is user buffer (call 3) +; BX is assign index (calls 2,3,4,5) +; CX is user number (call 1) +; DX is flag word (call 4) +; Outputs: If AL = 0 then the current user string is written to DS:DX +; and user CX is set to the user number +; If AL = 3 then CX bytes have been put at input ES:DI +; If AL = 5 then DX is flag word + +Procedure $UserOper,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup + PUSH AX + SUB AL,1 ; quick dispatch on 0,1 + POP AX + JB UserGet ; return to user the string + JZ UserSet ; set the current user + CMP AL,5 ; test for 2,3,4 or 5 + JBE UserPrint ; yep + MOV EXTERR_LOCUS,errLoc_Unk ; Extended Error Locus + error error_Invalid_Function ; not 0,1,2,3 + +UserGet: +; Transfer MYNAME to DS:DX +; Set Return CX to MYNUM + PUSH DS ; switch registers + POP ES + MOV DI,DX ; destination + MOV CX,[MYNUM] ; Get number + invoke get_user_stack + MOV [SI.User_CX],CX ; Set number return + Context DS ; point to DOSGroup +ASSUME DS:DOSGROUP + MOV SI,OFFSET DOSGroup:MyName ; point source to user string +UserMove: +ASSUME DS:NOTHING + MOV CX,15 + REP MOVSB ; blam. + XOR AX,AX ; 16th byte is 0 + STOSB +UserBye: + transfer sys_ret_ok ; no errors here + +UserSet: +ASSUME DS:NOTHING +; Transfer DS:DX to MYNAME +; CX to MYNUM + MOV [MYNUM],CX + MOV SI,DX ; user space has source + Context ES + MOV DI,OFFSET DOSGroup:MyName ; point dest to user string + INC [DiffNam] ; signal change + JMP UserMove + +UserPrint: + ASSUME ES:NOTHING +IF NOT Installed + transfer PRINTER_GETSET_STRING +ELSE + PUSH AX + MOV AX,(multNET SHL 8) OR 31 + INT 2FH + POP DX ; Clean stack + JNC OKPA + transfer SYS_RET_ERR + +OKPA: + transfer SYS_RET_OK +ENDIF + +EndProc $UserOper + +Break + +; +; GetVisDrv - correctly map non-spliced inuse drives +; +; Inputs: AL has drive identifier (0=default) +; Outputs: Carry Set - invalid drive/macro +; Carry Clear - AL has physical drive (0=A) +; ThisCDS points to CDS +; Registers modified: AL + +Procedure GetVisDrv,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup + CALL GetThisDrv ; get inuse drive + retc + SaveReg + LDS SI,ThisCDS + TEST [SI].curdir_flags,curdir_splice + RestoreReg + retz ; if not spliced, return OK + MOV [DrvErr],error_invalid_drive ;IFS. ;AN000; + STC ; signal error + return +EndProc GetVisDrv + +Break + +; +; GetThisDrv - look through a set of macros and return the current drive and +; macro pointer +; +; Inputs: AL has drive identifier (1=A, 0=default) +; Outputs: +; Carry Set - invalid drive/macro +; Carry Clear - AL has physical drive (0=A) +; ThisCDS points to macro +; Registers modified: AL + +Procedure GetThisDrv,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup + OR AL,AL ; are we using default drive? + JNZ GetMap ; no, go get the CDS pointers + MOV AL,[CurDrv] ; get the current drive + INC AL ; Counteract next instruction +GetMap: + DEC AL ; 0 = A + SaveReg ; save world + mov [EXTERR_LOCUS],errLOC_Disk + TEST fSharing,-1 ; Logical or Physical? + JZ Not_SRVC ; Logical + SaveReg + MOV WORD PTR ThisCDS,OFFSET DOSGroup:DummyCDS + MOV WORD PTR ThisCDS+2,CS ; ThisCDS = &DummyCDS; + ADD AL,'A' + CALL InitCDS ; InitCDS(c); + TEST ES:[DI.curdir_flags],curdir_inuse ; Clears carry + RestoreReg + JZ GetBerr ; Not a physical drive. + JMP SHORT GetBye ; carry clear + +Not_SRVC: + invoke GetCDSFromDrv + JC GetBerr2 ; Unassigned CDS -> return error already set + TEST [SI.curdir_flags],curdir_inuse ; Clears Carry + JNZ GetBye ; carry clear +GetBerr: + MOV AL,error_not_DOS_disk ;AN000;IFS. Formatted IFS drive + CMP WORD PTR [SI.curdir_devptr],0 ;AN000;IFS. dpb ptr =0 ? + JNZ notfat ;AN000;IFS. no +GetBerr2: + MOV AL,error_invalid_drive ;AN000;;IFS. invalid FAT drive +notfat: ;AN000; + MOV [DrvErr],AL ;AN000;;IFS. save this for IOCTL + mov [EXTERR_LOCUS],errLOC_UNK + STC +GetBye: RestoreReg ; restore world + return +EndProc GetThisDrv + +Break + +; +; GetCDSFromDrv - given a physical drive number, convert it to a CDS +; pointer, returning an error if the drive number is greater than the +; number of CDS's +; +; Inputs: AL is physical unit # A=0... +; Outputs: Carry Set if Bad Drive +; Carry Clear +; DS:SI -> CDS +; [THISCDS] = DS:SI +; Registers modified: DS,SI + +Procedure GetCDSFromDrv,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup + CMP AL,[CDSCount] ; is this a valid designator + JB GetCDS ; yes, go get the macro + STC ; signal error + return ; bye +GetCDS: + SaveReg + LDS SI,[CDSAddr] ; get pointer to table + MOV BL,SIZE CurDir_list ; size in convenient spot + MUL BL ; get net offset + ADD SI,AX ; convert to true pointer + MOV WORD PTR [ThisCDS],SI ; store convenient offset + MOV WORD PTR [ThisCDS+2],DS ; store convenient segment + RestoreReg + CLC ; no error + return ; bye! +EndProc GetCDSFromDrv + +CODE ends +END diff --git a/v4.0/src/DOS/MACRO2.ASM b/v4.0/src/DOS/MACRO2.ASM new file mode 100644 index 0000000..a3ff4cc --- /dev/null +++ b/v4.0/src/DOS/MACRO2.ASM @@ -0,0 +1,1281 @@ +; SCCSID = @(#)macro2.asm 1.2 85/07/23 +TITLE MACRO2 - Pathname and macro related internal routines +NAME MACRO2 +; +; TransFCB written +; TransPath written +; TransPathSet written +; TransPathNoSet Written +; Canonicalize written +; PathSep written +; SkipBack written +; CopyComponent written +; Splice written +; $NameTrans written +; DriveFromText +; TextFromDrive +; PathPref +; ScanPathChar +; +; Revision history: +; +; Created: MZ 4 April 1983 +; MZ 18 April 1983 Make TransFCB handle extended FCBs +; AR 2 June 1983 Define/Delete macro for NET redir. +; MZ 3 Nov 83 Fix InitCDS to reset length to 2 +; MZ 4 Nov 83 Fix NetAssign to use STRLEN only +; MZ 18 Nov 83 Rewrite string processing for subtree +; aliasing. +; BAS 3 Jan 85 ScanPathChar to search for path separator +; in null terminated string. +; +; MSDOS performs several types of name translation. First, we maintain for +; each valid drive letter the text of the current directory on that drive. +; For invalid drive letters, there is no current directory so we pretend to +; be at the root. A current directory is either the raw local directory +; (consisting of drive:\path) or a local network directory (consisting of +; \\machine\path. There is a limit on the point to which a .. is allowed. +; +; Given a path, MSDOS will transform this into a real from-the-root path +; without . or .. entries. Any component that is > 8.3 is truncated to +; this and all * are expanded into ?'s. +; +; The second part of name translation involves subtree aliasing. A list of +; subtree pairs is maintained by the external utility SUBST. The results of +; the previous 'canonicalization' are then examined to see if any of the +; subtree pairs is a prefix of the user path. If so, then this prefix is +; replaced with the other subtree in the pair. +; +; A third part involves mapping this "real" path into a "physical" path. A +; list of drive/subtree pairs are maintained by the external utility JOIN. +; The output of the previous translation is examined to see if any of the +; subtrees in this list are a prefix of the string. If so, then the prefix +; is replaced by the appropriate drive letter. In this manner, we can +; 'mount' one device under another. +; +; The final form of name translation involves the mapping of a user's +; logical drive number into the internal physical drive. This is +; accomplished by converting the drive number into letter:CON, performing +; the above translation and then converting the character back into a drive +; number. +; +; curdir_list STRUC +; curdir_text DB DIRSTRLEN DUP (?) ; text of assignment and curdir +; curdir_flags DW ? ; various flags +; curdir_devptr DD ? ; local pointer to DPB or net device +; curdir_ID DW ? ; cluster of current dir (net ID) +; DW ? +; curdir_end DW ? ; end of assignment +; curdir_list ENDS +; curdir_netID EQU DWORD PTR curdir_ID +; ;Flag word masks +; curdir_isnet EQU 1000000000000000B +; curdir_inuse EQU 0100000000000000B +; +; +; There are two main entry points: TransPath and TransFCB. TransPath will +; take a path and form the real text of the pathname with all . and .. +; removed. TransFCB will translate an FCB into a path and then invoke +; TransPath. +; +; Implementation note: CURDIR_End field points to the point in the text +; string where the user may back up to via .. It is the location of a +; separator character. For the root, it points at the leading /. For net +; assignments it points at the end (nul) of the initial assignment: +; A:/ \\foo\bar \\foo\bar\blech\bozo +; ^ ^ ^ +; A: -> d: /path/ path/ text +; +; A000 version 4.00 Jan. 1988 + +.xlist +; +; get the appropriate segment definitions +; +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGroup,CS:DOSGroup + +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +.cref +.list +.sall + +Installed = TRUE + + I_need Splices,BYTE ; TRUE => splices are being done. + I_need WFP_Start,WORD ; pointer to beginning of expansion + I_need Curr_Dir_End,WORD ; offset to end of current dir + I_need ThisCDS,DWORD ; pointer to CDS used + I_need ThisDPB,DWORD ; pointer to DPB used + I_need NAME1,11 ; Parse output of NameTrans + I_need OpenBuf,128 ; ususal destination of strings + I_need ExtFCB,BYTE ; flag for extended FCBs + I_need Sattrib,BYTE ; attribute of search + I_need fSplice,BYTE ; TRUE => do splice after canonicalize + I_need fSharing,BYTE ; TRUE => no redirection allowed + I_Need NoSetDir,BYTE ; TRUE => syscall is interested in + ; entry, not contents. We splice only + ; inexact matches + I_Need cMeta,BYTE ; count of meta chars in path + I_Need Temp_Var,WORD ;AN000; variable for temporary use 3/31/KK + I_Need DOS34_FLAG,WORD ;AN000; variable for dos34 + I_Need NO_FILTER_PATH,DWORD ;AN000; pointer to orignal path +Table SEGMENT + EXTRN CharType:BYTE +Table ENDS + +BREAK + +; +; TransFCB - Copy an FCB from DS:DX into a reserved area doing all of the +; gritty substitution. +; +; Inputs: DS:DX - pointer to FCB +; ES:DI - point to destination +; Outputs: Carry Set - invalid path in final map +; Carry Clear - FCB has been mapped into ES:DI +; Sattrib is set from possibly extended FCB +; ExtFCB set if extended FCB found +; Registers modified: most + +Procedure TransFCB,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup +PUBLIC MACRO001S,MACRO001E +MACRO001S: + LocalVar FCBTmp,15 +MACRO001E: + Enter + Context ES ; get DOSGroup addressability + SaveReg ; save away final destination + LEA DI,FCBTmp ; point to FCB temp area + MOV [ExtFCB],0 ; no extended FCB found + MOV [Sattrib],0 ; default search attributes + invoke GetExtended ; get FCB, extended or not + JZ GetDrive ; not an extended FCB, get drive + MOV AL,[SI-1] ; get attributes + MOV [SAttrib],AL ; store search attributes + MOV [ExtFCB],-1 ; signal extended FCB +GetDrive: + LODSB ; get drive byte + invoke GetThisDrv + jc BadPack + CALL TextFromDrive ; convert 0-based drive to text +; +; Scan the source to see if there are any illegal chars +; + MOV BX,OFFSET DOSGroup:CharType + IF DBCS ;AN000; +;----------------------------- Start of DBCS 2/13/KK + SaveReg ;AN000;; back over name, ext + MOV CX,8 ;AN000;; 8 chars in main part of name +FCBScan:LODSB ;AN000;; get a byte + invoke testkanj ;AN000; + jz notkanj2 ;AN000; + DEC CX ;AN000; + JCXZ VolidChck ;AN000;; Kanji half char screw up + LODSB ;AN000;; second kanji byte + jmp short Nextch ;AN000; +VolidChck: ;AN000; + TEST [SAttrib],attr_volume_id ;AN000;; volume id ? + JZ Badpack ;AN000;; no, error + OR [DOS34_FLAG],DBCS_VOLID ;AN000;; no, error + DEC CX ;AN000;; cx=-1 + INC SI ;AN000;; next char + JMP SHORT FCBScango ;AN000; +notkanj2: ;AN000; + XLAT ES:CharType ;AN000;;get bits + TEST AL,fFCB ;AN000; + JZ BadPack ;AN000; +NextCh: ;AN000; + LOOP FCBScan ;AN000; +FCBScango: ;AN000; + ADD CX,3 ;AN000;; Three chars in extension +FCBScanE: ;AN000; + LODSB ;AN000; + invoke testkanj ;AN000; + jz notkanj3 ;AN000; + DEC CX ;AN000; + JCXZ BadPack ;AN000;; Kanji half char problem + LODSB ;AN000;; second kanji byte + jmp short NextChE ;AN000; +notkanj3: ;AN000; + XLAT ES:CharType ;AN000;; get bits + TEST AL,fFCB ;AN000; + JZ BadPack ;AN000; +NextChE: ;AN000; + LOOP FCBScanE ;AN000; +;----------------------------- End of DBCS 2/13/KK + ELSE + + MOV CX,11 + SaveReg ; back over name, ext +FCBScan:LODSB ; get a byte + XLAT ES:CharType ; get bits + TEST AL,fFCB + JZ BadPack +NextCh: LOOP FCBScan + ENDIF + RestoreReg + MOV BX,DI + invoke PackName ; crunch the path + RestoreReg ; get original destination + Context DS ; get DS addressability + LEA SI,FCBTmp ; point at new pathname + CMP BYTE PTR [BX],0 + JZ BadPack + SaveReg + CALL TransPathSet ; convert the path + RestoreReg + JNC FCBRet ; bye with transPath error code +BadPack: + STC + MOV AL,error_path_not_found +FCBRet: Leave + return +EndProc TransFCB,NoCheck + +BREAK + +; +; TransPath - copy a path from DS:SI to ES:DI, performing component string +; substitution, insertion of current directory and fixing . and .. +; entries. Perform splicing. Allow input string to match splice +; exactly. +; +; TransPathSet - Same as above except No splicing is performed if input path +; matches splice. +; +; TransPathNoSet - No splicing/local using is performed at all. +; +; The following anomalous behaviour is required: +; +; Drive letters on devices are ignored. (set up DummyCDS) +; Paths on devices are ignored. (truncate to 0-length) +; Raw net I/O sets ThisCDS => NULL. +; fSharing => dummyCDS and no subst/splice. Only canonicalize. +; +; Other behaviour: +; +; ThisCDS set up. +; FatRead done on local CDS. +; ValidateCDS done on local CDS. +; +; Brief flowchart: +; +; if fSharing then +; set up DummyCDS (ThisCDS) +; canonicalize (sets cMeta) +; splice +; fatRead +; return +; if \\ or d:\\ lead then +; set up null CDS (ThisCDS) +; canonicalize (sets cMeta) +; return +; if device then +; set up dummyCDS (ThisCDS) +; canonicalize (sets cMeta) +; return +; if file then +; getCDS (sets (ThisCDS) from name) +; validateCDS (may reset current dir) +; Copy current dir +; canonicalize (set cMeta) +; splice +; generate correct CDS (ThisCDS) +; if local then +; fatread +; return +; +; Inputs: DS:SI - point to ASCIZ string path +; DI - point to buffer in DOSGroup +; Outputs: Carry Set - invalid path specification: too many .., bad +; syntax, etc. or user FAILed to I 24. +; WFP_Start - points to beginning of buffer +; Curr_Dir_End - points to end of current dir in path +; DS - DOSGroup +; Registers modified: most + +Procedure TransPath,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup + XOR AL,AL + JMP SHORT SetSplice + Entry TransPathSet + MOV AL,-1 +SetSplice: + MOV NoSetDir,AL ; NoSetDir = !fExact; + MOV AL,-1 + Entry TransPathNoSet + MOV WORD PTR [NO_FILTER_PATH],SI ;AN000;;IFS. save old path for IFS + MOV WORD PTR [NO_FILTER_PATH+2],DS ;AN000;;IFS. + + MOV fSplice,AL ; fSplice = TRUE; + MOV cMeta,-1 + MOV WFP_Start,DI + MOV Curr_Dir_End,-1 ; crack from start + Context ES + LEA BP,[DI+TEMPLEN] ; end of buffer +; +; if this is through the server dos call, fsharing is set. We set up a +; dummy cds and let the operation go. +; + TEST fSharing,-1 ; if no sharing + JZ CheckUNC ; skip to UNC check +; +; ES:DI point to buffer +; + CALL DriveFromText ; get drive and advance DS:SI + invoke GetThisDrv ; Set ThisCDS and convert to 0-based + jc NoPath + CALL TextFromDrive ; drop in new + LEA BX,[DI+1] ; backup limit + CALL Canonicalize ; copy and canonicalize + retc ; errors +; +; Perform splices for net guys. +; + Context DS + MOV SI,wfp_Start ; point to name + TEST fSplice,-1 + JZ NoServerSplice + CALL Splice +NoServerSplice: + Context DS ; for FATREAD + LES DI,ThisCDS ; for fatread + EnterCrit critDisk + Invoke FatRead_CDS + LeaveCrit critDisk +NoPath: + MOV AL,error_path_not_found ; Set up for possible bad path error + return ; any errors are in Carry flag + ASSUME DS:NOTHING +; +; Let the network decide if the name is for a spooled device. It will map +; the name if so. +; +CheckUnc: + MOV WORD PTR ThisCDS,-1 ; NULL thisCDS + CallInstall NetSpoolCheck,multNet,35 + JNC UNCDone +; +; At this point the name is either a UNC-style name (prefixed with two leading +; \\s) or is a local file/device. Remember that if a net-spooled device was +; input, then the name has been changed to the remote spooler by the above net +; call. Also, there may be a drive in front of the \\. +; +NO_CHECK: + CALL DriveFromText ; eat drive letter + PUSH AX ; save it + MOV AX,WORD PTR [SI] ; get first two bytes of path + Invoke PathChrCmp ; convert to normal form + XCHG AH,AL ; swap for second byte + Invoke PathChrCmp ; convert to normal form + JNZ CheckDevice ; not a path char + CMP AH,AL ; are they same? + JNZ CheckDevice ; nope +; +; We have a UNC request. We must copy the string up to the beginning of the +; local machine root path +; + + POP AX + MOVSW ; get the lead \\ +UNCCpy: LODSB ; get a byte + IF DBCS ;AN000; +;----------------------------- Start of DBCS 2/23/KK + invoke testkanj ;AN000; + jz notkanj1 ;AN000; + STOSB ;AN000; + LODSB ;AN000; + OR AL,AL ;AN000; + JZ UNCTerm ;AN000;; Ignore half kanji error for now + STOSB ;AN000; + jmp UNCCpy ;AN000; +notkanj1: ;AN000; +;----------------------------- End of DBCS 2/23/KK + ENDIF ;AN000; + invoke UCase ;AN000;; convert the char + OR AL,AL + JZ UNCTerm ; end of string. All done. + Invoke PathChrCmp ; is it a path char? + MOV BX,DI ; backup position + STOSB + JNZ UNCCpy ; no, go copy + CALL Canonicalize ; wham (and set cMeta) +UNCDone: + Context DS + IF DBCS +;----------------------------- Start of DBCS 2/23/KK + retc ;AN000; Return if error from Canonicalize + +; Although Cononicalize has done lots of good things for us it may also have +; done e5 to 05 conversion on the fisrt char following a path sep char which is +; not wanted on a UNC request as this should be left for the remote station. +; The simplest thing to do is check for such conversions and convert them back +; again. +; This check loop is also called from the DoFile section of TransPath if the +; file is a remote file. Entry point when called is TP_check05 with the +; inputs/outputs as follows; +; Inputs : ES:DI = Buffer to check for re-conversion +; Outputs: None +; Used : DI,AX + + + MOV DI,WFP_start ;AN000;; ES:DI points to converted string +TP_check05: ;AN000; + MOV AL,BYTE PTR ES:[DI] ;AN000;; Get character from path + OR AL,AL ;AN000;; End of null terminated path? + JZ TP_end05 ;AN000;; Finished, CF =0 from OR (ret success) + invoke testkanj ;AN000;; Kanji lead character? + JZ TP_notK ;AN000;; Check for path seperator if not + INC DI ;AN000;; Bypass Kanji second byte + JMP TP_nxt05 ;AN000;; Go to check next character +TP_notK: ;AN000; + invoke PathChrCmp ;AN000;; Is it a path seperator char? + JNZ TP_nxt05 ;AN000;; Check next character if not + CMP BYTE PTR ES:[DI+1],05 ;AN000;; 05 following path sep char? + JNZ TP_nxt05 ;AN000;; Check next character if not + MOV BYTE PTR ES:[DI+1],0E5h ;AN000;; Convert 05 back to E5 +TP_nxt05: ;AN000; + INC DI ;AN000;; Point to next char in path + JMP TP_check05 ;AN000;; Test all chars in path +TP_end05: +;----------------------------- End of DBCS 2/23/KK + ENDIF ;AN000; + return ; return error code + + ASSUME DS:NOTHING +UNCTerm: + STOSB ;AN000; + JMP UNCDone ;AN000; + +CheckDevice: +; +; Check DS:SI for device. First eat any path stuff +; + POP AX ; retrieve drive info + CMP BYTE PTR DS:[SI],0 ; check for null file + JNZ CheckPath + MOV AL,error_file_not_found ; bad file error + STC ; signal error on null input + RETURN ; bye! +CheckPath: + SaveReg ; save drive number + Invoke CheckThisDevice ; snoop for device + RestoreReg ; get drive letter back + JNC DoFile ; yes we have a file. +; +; We have a device. AX has drive letter. At this point we may fake a CDS ala +; sharing DOS call. We know by getting here that we are NOT in a sharing DOS +; call. +; + MOV fSharing,-1 ; simulate sharing dos call + invoke GetThisDrv ; set ThisCDS and init DUMMYCDS + MOV fSharing,0 ; +; +; Now that we have noted that we have a device, we put it into a form that +; getpath can understand. Normally getpath requires d:\ to begin the input +; string. We relax this to state that if the d:\ is present then the path +; may be a file. If D:/ (note the forward slash) is present then we have +; a device. +; + CALL TextFromDrive + MOV AL,'/' ; path sep. + STOSB + invoke StrCpy ; move remainder of string + CLC ; everything OK. + Context DS ; remainder of OK stuff + return +; +; We have a file. Get the raw CDS. +; +DoFile: + ASSUME DS:NOTHING + invoke GetVisDrv ; get proper CDS + MOV AL,error_path_not_found ; Set up for possible bad file error + retc ; CARRY set -> bogus drive/spliced +; +; ThisCDS has correct CDS. DS:SI advanced to point to beginning of path/file. +; Make sure that CDS has valid directory; ValidateCDS requires a temp buffer +; Use the one that we are going to use (ES:DI). +; + SaveReg ; save all string pointers. + invoke ValidateCDS ; poke CDS amd make everything OK + RestoreReg ; get back pointers + MOV AL,error_path_not_found ; Set up for possible bad path error + retc ; someone failed an operation +; +; ThisCDS points to correct CDS. It contains the correct text of the +; current directory. Copy it in. +; + SaveReg + LDS SI,ThisCDS ; point to CDS + MOV BX,DI ; point to destination + ADD BX,[SI].curdir_end ; point to backup limit +; LEA SI,[SI].curdir_text ; point to text + LEA BP,[DI+TEMPLEN] ; regenerate end of buffer + IF DBCS ;AN000; +;------------------------ Start of DBCS 2/13/KK +Kcpylp: ;AN000; + LODSB ;AN000; + invoke TestKanj ;AN000; + jz Notkanjf ;AN000; + STOSB ;AN000; + MOVSB ;AN000; + CMP BYTE PTR [SI],0 ;AN000; + JNZ Kcpylp ;AN000; + MOV AL, '\' ;AN000; + STOSB ;AN000; + JMP SHORT GetOrig ;AN000; +Notkanjf: ;AN000; + STOSB ;AN000; + OR AL,AL ;AN000; + JNZ Kcpylp ;AN000; + DEC DI ;AN000;; point to NUL byte + +;------------------------ End of DBCS 2/13/KK + ELSE ;AN000; + invoke FStrCpy ; copy string. ES:DI point to end + DEC DI ; point to NUL byte + ENDIF ;AN000; +; +; Make sure that there is a path char at end. +; + MOV AL,'\' + CMP ES:[DI-1],AL + JZ GetOrig + STOSB +; +; Now get original string. +; +GetOrig: + DEC DI ; point to path char + RestoreReg +; +; BX points to the end of the root part of the CDS (at where a path char +; should be) . Now, we decide whether we use this root or extend it with the +; current directory. See if the input string begins with a leading \ +; + CALL PathSep ; is DS:SI a path sep? + JNZ PathAssure ; no, DI is correct. Assure a path char + OR AL,AL ; end of string? + JZ DoCanon ; yes, skip. +; +; The string does begin with a \. Reset the beginning of the canonicalization +; to this root. Make sure that there is a path char there and advance the +; source string over all leading \'s. +; + MOV DI,BX ; back up to root point. +SkipPath: + LODSB + invoke PathChrCmp + JZ SkipPath + DEC SI + OR AL,AL + JZ DoCanon +; +; DS:SI start at some file name. ES:DI points at some path char. Drop one in +; for yucks. +; +PathAssure: + MOV AL,'\' + STOSB +; +; ES:DI point to the correct spot for canonicalization to begin. +; BP is the max extent to advance DI +; BX is the backup limit for .. +; +DoCanon: + CALL Canonicalize ; wham. + retc ; badly formatted path. + IF DBCS ;AN000; +;--------------------- Start of DBCS 2/13/KK +; Although Cononicalize has done lots of good things for us it may also have +; done e5 to 05 conversion on the fisrt char following a path sep char which is +; not wanted if this a remote file as this should be left for the remote +; station. Check for a leading \\ in the path buffer and call TP_check05 to +; reconvert if found. + + MOV DI,WFP_start ;AN000;; ES:DI points to string + MOV AX,WORD PTR ES:[DI] ;AN000;; Get leading 2 chars from path buffer + invoke PathChrCmp ;AN000;; First char a path char? + JNZ TP_notremote ;AN000;; Not remote if not. + invoke PathChrCmp ;AN000;; Second char a path char? + JNZ TP_notremote ;AN000;; Not remote if not + CALL TP_check05 ;AN000;; Remote so convert 05 back to e5 +TP_notremote: ;AN000; +;--------------------- End of DBCS 2/13/KK + ENDIF +; +; The string has been moved to ES:DI. Reset world to DOS context, pointers +; to wfp_start and do string substitution. BP is still the max position in +; buffer. +; + Context DS + MOV DI,wfp_start ; DS:SI point to string + LDS SI,ThisCDS ; point to CDS + ASSUME DS:NOTHING +; LEA SI,[SI].curdir_text ; point to text + CALL PathPref ; is there a prefix? + JNZ DoSplice ; no, do splice +; +; We have a match. Check to see if we ended in a path char. +; + IF DBCS ;AN000; +;---------------------------- Start of DBCS 2/13/KK + PUSH BX ;AN000; + MOV BX,SI ;AN000; + MOV SI,WORD PTR ThisCDS ;AN000;; point to CDS +LOOKDUAL: ;AN000; + MOV AL,BYTE PTR [SI] ;AN000; + invoke TESTKANJ ;AN000; + JZ ONEINC ;AN000; + INC SI ;AN000; + INC SI ;AN000; + CMP SI,BX ;AN000; + JB LOOKDUAL ;AN000; + POP BX ;AN000;; Last char was KANJI, don't look back + JMP SHORT Pathline ;AN000;; for path sep, there isn't one. + ;AN000; +ONEINC: ;AN000; + INC SI ;AN000; + CMP SI,BX ;AN000; + JB LOOKDUAL ;AN000; + POP BX ;AN000; +;------------------------ End of DBCS 2/13/KK + ENDIF ;AN000; + MOV AL,DS:[SI-1] ; last char to match + Invoke PathChrCmp ; did we end on a path char? (root) + JZ DoSplice ; yes, no current dir here. +Pathline: ; 2/13/KK + CMP BYTE PTR ES:[DI],0 ; end at NUL? + JZ DoSplice + INC DI ; point to after current path char + MOV Curr_Dir_End,DI ; point to correct spot +; +; Splice the result. +; +DoSplice: + Context DS ; back to DOSGROUP + MOV SI,wfp_Start ; point to beginning of string + XOR CX,CX + TEST fSplice,-1 + JZ SkipSplice + CALL Splice ; replaces in place. +SkipSplice: + ASSUME DS:NOTHING +; +; The final thing is to assure ourselves that a FATREAD is done on the local +; device. +; + Context DS + LES DI,ThisCDS ; point to correct drive + TEST ES:[DI].curdir_flags,curdir_isnet + retnz ; net, no fatread necessary + JCXZ Done + EnterCrit critDisk + invoke FatRead_CDS + LeaveCrit critDisk + MOV AL,error_path_not_found ; Set up for possible bad path error +Done: return ; any errors in carry flag. +EndProc TransPath + +BREAK + +; +; Canonicalize - copy path removing . and .. entries. +; +; Inputs: DS:SI - point to ASCIZ string path +; ES:DI - point to buffer +; BX - backup limit (offset from ES) points to slash +; BP - end of buffer +; Outputs: Carry Set - invalid path specification: too many .., bad +; syntax, etc. +; Carry Clear - +; DS:DI - advanced to end of string +; ES:DI - advanced to end of canonicalized form after nul +; Registers modified: AX CX DX (in addition to those above) + +Procedure Canonicalize,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup +; +; We copy all leading path separators. +; + LODSB ; while (PathChr (*s)) + Invoke PathChrCmp + IF DBCS + JNZ CanonDec0 ; 2/19/KK + ELSE + JNZ CanonDec + ENDIF + CMP DI,BP ; if (d > dlim) + JAE CanonBad ; goto error; + STOSB + JMP Canonicalize ; *d++ = *s++; + IF DBCS ;AN000; +CanonDec0: ;AN000; 2/19/KK +; mov cs:Temp_Var,di ;AN000; 3/31/KK + ENDIF ;AN000; +CanonDec: + DEC SI +; +; Main canonicalization loop. We come here with DS:SI pointing to a textual +; component (no leading path separators) and ES:DI being the destination +; buffer. +; +CanonLoop: +; +; If we are at the end of the source string, then we need to check to see that +; a potential drive specifier is correctly terminated with a path sep char. +; Otherwise, do nothing +; + XOR AX,AX + CMP [SI],AL ; if (*s == 0) { + JNZ DoComponent + IF DBCS ;AN000; + call chk_last_colon ;AN000; 2/18/KK + ELSE ;AN000; + CMP BYTE PTR ES:[DI-1],':' ; if (d[-1] == ':') + ENDIF ;AN000; + JNZ DoTerminate + MOV AL,'\' ; *d++ = '\'; + STOSB + MOV AL,AH +DoTerminate: + STOSB ; *d++ = 0; + CLC ; return (0); + return + IF DBCS ;AN000; +;---------------- Start of DBCS 2/18/KK +chk_last_colon proc ;AN000; + push si ;AN000; + push ax ;AN000; + push bx ;AN000; + mov si,[WFP_START] ;AN000;;PTM. for cd .. use beginning of buf + cmp si,di ;AN000;; no data stored ? + jb CLC02 ;AN000;;PTM. for cd .. + inc si ;AN000;; make NZ flag + JMP SHORT CLC09 ;AN000; +CLC02: ;AN000; + mov bx,di ;AN000; + dec bx ;AN000; +CLC_lop: ;AN000; + cmp si,bx ;AN000; + jb CLC00 ;AN000; + jne CLC09 ;AN000; +CLC01: ;AN000; + CMP BYTE PTR ES:[DI-1],':' ;AN000;; if (d[-1] == ':') + jmp CLC09 ;AN000; +CLC00: ;AN000; + mov al,es:[si] ;AN000; + inc si ;AN000; + invoke testkanj ;AN000; + je CLC_lop ;AN000; + inc si ;AN000; + jmp CLC_lop ;AN000; +CLC09: ;AN000; + pop bx ;AN000; + pop ax ;AN000; + pop si ;AN000; + ret ;AN000; +chk_last_colon endp ;AN000; +;---------------- Endt of DBCS 2/18/KK + ENDIF ;AN000; + +CanonBad: + CALL ScanPathChar ; check for path chars in rest of string + MOV AL,error_path_not_found ; Set up for bad path error + JZ PathEnc ; path character encountered in string + MOV AL,error_file_not_found ; Set bad file error +PathEnc: + STC + return +; +; We have a textual component that we must copy. We uppercase it and truncate +; it to 8.3 +; +DoComponent: ; } + CALL CopyComponent ; if (!CopyComponent (s, d)) + retc ; return (-1); +; +; We special case the . and .. cases. These will be backed up. +; + CMP WORD PTR ES:[DI],'.' + (0 SHL 8) + JZ Skip1 + CMP WORD PTR ES:[DI],'..' + JNZ CanonNormal + DEC DI ; d--; +Skip1: CALL SkipBack ; SkipBack (); + MOV AL,error_path_not_found ; Set up for possible bad path error + retc + JMP CanonPath ; } +; +; We have a normal path. Advance destination pointer over it. +; +CanonNormal: ; else + ADD DI,CX ; d += ct; +; +; We have successfully copied a component. We are now pointing at a path +; sep char or are pointing at a nul or are pointing at something else. +; If we point at something else, then we have an error. +; +CanonPath: + CALL PathSep + JNZ CanonBad ; something else... +; +; Copy the first path char we see. +; + LODSB ; get the char + Invoke PathChrCmp ; is it path char? + JNZ CanonDec ; no, go test for nul + CMP DI,BP ; beyond buffer end? + JAE CanonBad ; yep, error. + STOSB ; copy the one byte +; +; Skip all remaining path chars +; +CanonPathLoop: + LODSB ; get next byte + Invoke PathChrCmp ; path char again? + JZ CanonPathLoop ; yep, grab another + DEC SI ; back up + JMP CanonLoop ; go copy component +EndProc Canonicalize + +BREAK + +; +; PathSep - look at DS:SI and see if char is / \ or NUL +; Inputs: DS:SI - point to a char +; Outputs: AL has char from DS:SI (/ => \) +; Zero set if AL is / \ or NUL +; Zero reset otherwise +; Registers modified: AL + +Procedure PathSep,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup + MOV AL,[SI] ; get the character + entry PathSepGotCh ; already have character + OR AL,AL ; test for zero + retz ; return if equal to zero (NUL) + invoke PathChrCmp ; check for path character + return ; and return HIS determination +EndProc PathSep + +BREAK + +; +; SkipBack - look at ES:DI and backup until it points to a / \ +; Inputs: ES:DI - point to a char +; BX has current directory back up limit (point to a / \) +; Outputs: ES:DI backed up to point to a path char +; AL has char from output ES:DI (path sep if carry clear) +; Carry set if illegal backup +; Carry Clear if ok +; Registers modified: DI,AL + +Procedure SkipBack,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup + IF DBCS ;AN000; +;-------------------------- Start of DBCS 2/13/KK + PUSH DS ;AN000; + PUSH SI ;AN000; + PUSH CX ;AN000; + PUSH ES ;AN000; + POP DS ;AN000; + MOV SI,BX ;AN000;; DS:SI -> start of ES:DI string + MOV CX,DI ;AN000;; Limit of forward scan is input DI + MOV AL,[SI] ;AN000; + invoke PathChrCmp ;AN000; + JNZ SkipBadP ;AN000;; Backup limit MUST be path char + CMP DI,BX ;AN000; + JBE SkipBadP ;AN000; + MOV DI,BX ;AN000;; Init backup point to backup limit +Skiplp: ;AN000; + CMP SI,CX ;AN000; + JAE SkipOK ;AN000;; Done, DI is correct backup point + LODSB ;AN000; + invoke Testkanj ;AN000; + jz Notkanjv ;AN000; + lodsb ;AN000;; Skip over second kanji byte + JMP Skiplp ;AN000; +NotKanjv: ;AN000; + invoke PathChrCmp ;AN000; + JNZ Skiplp ;AN000;; New backup point + MOV DI,SI ;AN000;; DI point to path sep + DEC DI ;AN000; + jmp Skiplp ;AN000; +SkipOK: ;AN000; + MOV AL,ES:[DI] ;AN000;; Set output AL + CLC ;AN000;; return (0); + POP CX ;AN000; + POP SI ;AN000; + POP DS ;AN000; + return ;AN000; + ;AN000; +SkipBadP: ;AN000; + POP CX ;AN000; + POP SI ;AN000; + POP DS ;AN000; +;-------------------------- End of DBCS 2/13/KK + ELSE ;AN000; + CMP DI,BX ; while (TRUE) { + JB SkipBad ; if (d < dlim) + DEC DI ; goto err; + MOV AL,ES:[DI] ; if (pathchr (*--d)) + invoke PathChrCmp ; break; + JNZ SkipBack ; } + CLC ; return (0); + return ; + ENDIF ;AN000; +SkipBad: ;err: + MOV AL,error_path_not_found ; bad path error + STC ; return (-1); + return ; +EndProc SkipBack + +Break + +; +; CopyComponent - copy a file component from a path string (DS:SI) into ES:DI +; +; Inputs: DS:SI - source path +; ES:DI - destination +; ES:BP - end of buffer +; Outputs: Carry Set - too long +; Carry Clear - DS:SI moved past component +; CX has length of destination +; Registers modified: AX,CX,DX + +Procedure CopyComponent,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup +CopyBP EQU WORD PTR [BP] +CopyD EQU DWORD PTR [BP+2] +CopyDoff EQU WORD PTR [BP+2] +CopyS EQU DWORD PTR [BP+6] +CopySoff EQU WORD PTR [BP+6] +CopyTemp EQU BYTE PTR [BP+10] + SUB SP,14 ; room for temp buffer + SaveReg + MOV BP,SP + MOV AH,'.' + LODSB + STOSB + CMP AL,AH ; if ((*d++=*s++) == '.') { + JNZ NormalComp + CALL PathSep ; if (!pathsep(*s)) + JZ NulTerm +TryTwoDot: + LODSB ; if ((*d++=*s++) != '.' + STOSB + CMP AL,AH + JNZ CopyBad + CALL PathSep + JNZ CopyBad ; || !pathsep (*s)) +NulTerm: ; return -1; + XOR AL,AL ; *d++ = 0; + STOSB + MOV CopySoff,SI + JMP SHORT GoodRet ; } +NormalComp: ; else { + MOV SI,CopySoff + Invoke NameTrans ; s = NameTrans (s, Name1); + CMP SI,CopySOff ; if (s == CopySOff) + JZ CopyBad ; return (-1); + TEST fSharing,-1 ; if (!fSharing) { + JNZ DoPack + AND DL,1 ; cMeta += fMeta; + ADD cMeta,DL ; if (cMeta > 0) + JG CopyBad ; return (-1); + JNZ DoPack ; else + OR DL,DL ; if (cMeta == 0 && fMeta == 0) + JZ CopyBadPath ; return (-1); +DoPack: ; } + MOV CopySoff,SI + Context DS + MOV SI,OFFSET DOSGroup:NAME1 + LEA DI,CopyTemp + SaveReg + Invoke PackName ; PackName (Name1, temp); + RestoreReg + Invoke StrLen ; if (strlen(temp)+d > bp) + DEC CX + ADD CX,CopyDoff + CMP CX,CopyBP + JAE CopyBad ; return (-1); + MOV SI,DI ; strcpy (d, temp); + LES DI,CopyD + Invoke FStrCpy +GoodRet: ; } + CLC + JMP SHORT CopyEnd ; return 0; +CopyBad: + STC + CALL ScanPathChar ; check for path chars in rest of string + MOV AL,error_file_not_found ; Set up for bad file error + JNZ CopyEnd +CopyBadPath: + STC + MOV AL,error_path_not_found ; Set bad path error +CopyEnd: + RestoreReg + LAHF + ADD SP,14 ; reclaim temp buffer + Invoke Strlen + DEC CX + SAHF + return +EndProc CopyComponent,NoCheck + +Break + +; +; Splice - take a string and substitute a prefix if one exists. Change +; ThisCDS to point to physical drive CDS. +; Inputs: DS:SI point to string +; NoSetDir = TRUE => exact matches with splice fail +; Outputs: DS:SI points to thisCDS +; ES:DI points to DPB +; String at DS:SI may be reduced in length by removing prefix +; and substituting drive letter. +; CX = 0 If no splice done +; CX <> 0 otherwise +; ThisCDS points to proper CDS if spliced, otherwise it is +; left alone +; ThisDPB points to proper DPB +; Registers modified: DS:SI, ES:DI, BX,AX,CX + +Procedure Splice,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup + TEST Splices,-1 + JZ AllDone + SaveReg <,> ; TmpCDS = ThisCDS + SaveReg + RestoreReg + XOR AX,AX ; for (i=1; s = GetCDSFromDrv (i); i++) +SpliceScan: + invoke GetCDSFromDrv + JC SpliceDone + INC AL + TEST [SI.curdir_flags],curdir_splice + JZ SpliceScan ; if ( Spliced (i) ) { + SaveReg + CALL PathPref ; if (!PathPref (s, d)) + JZ SpliceFound ; +SpliceSkip: + RestoreReg + JMP SpliceScan ; continue; +SpliceFound: + CMP BYTE PTR ES:[DI],0 ; if (*s || NoSetDir) { + JNZ SpliceDo + TEST NoSetDir,-1 + JNZ SpliceSkip +SpliceDo: + MOV SI,DI ; p = src + strlen (p); + SaveReg + RestoreReg + CALL TextFromDrive1 ; src = TextFromDrive1(src,i); + MOV AX,Curr_Dir_End + OR AX,AX + JS NoPoke + ADD AX,DI ; curdirend += src-p; + SUB AX,SI + MOV Curr_Dir_End,AX +NoPoke: + CMP BYTE PTR [SI],0 ; if (*p) + JNZ SpliceCopy ; *src++ = '\\'; + MOV AL,"\" + STOSB +SpliceCopy: ; strcpy (src, p); + invoke FStrCpy + ADD SP,4 ; throw away saved stuff + OR CL,1 ; signal splice done. + JMP SHORT DoSet ; return; +SpliceDone: ; } + ASSUME DS:NOTHING ; ThisCDS = TmpCDS; + RestoreReg <,> +AllDone: + XOR CX,CX +DoSet: + LDS SI,ThisCDS ; ThisDPB = ThisCDS->devptr; + LES DI,[SI].curdir_devptr + MOV WORD PTR ThisDPB,DI + MOV WORD PTR ThisDPB+2,ES + return +EndProc Splice + +Break <$NameTrans - partially process a name> + +; +; $NameTrans - allow users to see what names get mapped to. This call +; performs only string substitution and canonicalization, not splicing. Due +; to Transpath playing games with devices, we need to insure that the output +; has drive letter and : in it. +; +; Inputs: DS:SI - source string for translation +; ES:DI - pointer to buffer +; Outputs: +; Carry Clear +; Buffer at ES:DI is filled in with data +; ES:DI point byte after nul byte at end of dest string in buffer +; Carry Set +; AX = error_path_not_found +; Registers modified: all + +Procedure $NameTrans,Near + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup + SaveReg + MOV DI,OFFSET DOSGroup:OpenBuf + CALL TransPath ; to translation (everything) + RestoreReg + JNC TransOK + transfer SYS_Ret_Err +TransOK: + MOV SI,OFFSET DOSGroup:OpenBuf + Context DS +GotText: + Invoke FStrCpy + Transfer SYS_Ret_OK +EndProc $NameTrans + +Break + +; +; DriveFromText - examine DS:SI and remove a drive letter, advancing the +; pointer. +; +; Inputs: DS:SI point to a text string +; Outputs: AL has drive number +; DS:SI advanced +; Registers modified: AX,SI. + +Procedure DriveFromText,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING + XOR AL,AL ; drive = 0; + CMP BYTE PTR [SI],0 ; if (*s && + retz + CMP BYTE PTR [SI+1],':' ; s[1] == ':') { + retnz + IF DBCS ;AN000; +;--------------------- Start of DBCS 2/18/KK + push ax ;AN000; + mov al,[si] ;AN000; + invoke testkanj ;AN000; + pop ax ;AN000; + retnz ;AN000; +;--------------------- End of DBCS 2/18/KK + ENDIF ;AN000; + LODSW ; drive = (*s | 020) - 'a'+1; + OR AL,020h + SUB AL,'a'-1 ; s += 2; + retnz + MOV AL,-1 ; nuke AL... + return ; } +EndProc DriveFromText + +Break + +; +; TextFromDrive - turn AL into a drive letter: and put it at es:di with +; trailing :. TextFromDrive1 takes a 1-based number. +; +; Inputs: AL has 0-based drive number +; Outputs: ES:DI advanced +; Registers modified: AX + +Procedure TextFromDrive,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING + INC AL + Entry TextFromDrive1 + ADD AL,'A'-1 ; *d++ = drive-1+'A'; + MOV AH,":" ; strcat (d, ":"); + STOSW + return +EndProc TextFromDrive + +Break + +; +; PathPref - compare DS:SI with ES:DI to see if one is the prefix of the +; other. Remember that only at a pathchar break are we allowed to have a +; prefix: A:\ and A:\FOO +; +; Inputs: DS:SI potential prefix +; ES:DI string +; Outputs: Zero set => prefix found +; DI/SI advanced past matching part +; Zero reset => no prefix, DS/SI garbage +; Registers modified: CX + +Procedure PathPref,NEAR + Invoke DStrLen ; get length + DEC CX ; do not include nul byte + IF DBCS ;AN000; +;----------------------- Start of DBCS 2/13/KK + SaveReg ;AN000;; save char register +CmpLp: ;AN000; + MOV AL,[SI] ;AN000; + invoke Testkanj ;AN000; + jz NotKanj9 ;AN000; + CMPSW ;AN000; + JNZ Prefix ;AN000; + DEC CX ;AN000; + LOOP CmpLp ;AN000; + JMP SHORT NotSep ;AN000; +NotKanj9: ;AN000; + CMPSB ;AN000; + JNZ Prefix ;AN000; + LOOP CmpLp ;AN000; +;----------------------- End of DBCS 2/13/KK + ELSE ;AN000; + REPZ CMPSB ; compare + retnz ; if NZ then return NZ + SaveReg ; save char register + ENDIF ;AN000; + MOV AL,[SI-1] ; get last byte to match + Invoke PathChrCmp ; is it a path char (Root!) + JZ Prefix ; yes, match root (I hope) +NotSep: ; 2/13/KK + MOV AL,ES:[DI] ; get next char to match + CALL PathSepGotCh ; was it a pathchar? +Prefix: + RestoreReg ; get back original + return +EndProc PathPref + +Break + +; +; ScanPathChar - search through the string (pointed to by DS:SI) for +; a path separator. +; +; Input: DS:SI target string (null terminated) +; Output: Zero set => path separator encountered in string +; Zero clear => null encountered +; Registers modified: SI + +Procedure ScanPathChar,NEAR + LODSB ; fetch a character + IF DBCS ;AN000; + invoke TestKanj ;AN000;; 2/13/KK + jz NotKanjr ;AN000;; 2/13/KK + LODSB ;AN000;; 2/13/KK + OR AL,AL ;AN000;; 2/13/KK 3/31/removed + JNZ ScanPathChar ;AN000;; 2/13/KK 3/31/removed + INC AL ;AN000;; 2/13/KK + return ;AN000;; 2/13/KK + ;AN000; +NotKanjr: ;AN000;; 2/13/KK + ENDIF ;AN000; + call PathSepGotCh + JNZ ScanPathChar ; not \, / or NUL => go back for more + invoke PathChrCmp ; path separator? + return +EndProc ScanPathChar + +CODE ends +END diff --git a/v4.0/src/DOS/MAKEFILE b/v4.0/src/DOS/MAKEFILE new file mode 100644 index 0000000..12912c4 --- /dev/null +++ b/v4.0/src/DOS/MAKEFILE @@ -0,0 +1,221 @@ +#*************************** Makefile for DOS *************************** + +msg =..\messages +inc =..\inc +hinc =..\hinc +make =nmake -i +dos =. + +# +###################### Dependencies begin here ########################## +# + +all: msdos.sys + +msdos.cl1: msdos.skl \ + $(msg)\$(COUNTRY).msg + +dossym.inc: $(inc)\dosmac.inc $(inc)\bpb.inc \ + $(inc)\buffer.inc $(inc)\sysvar.inc $(inc)\vector.inc \ + $(inc)\mult.inc $(inc)\dirent.inc $(inc)\dpb.inc $(inc)\curdir.inc \ + $(inc)\cpmfcb.inc $(inc)\find.inc $(inc)\pdb.inc $(inc)\exe.inc \ + $(inc)\sf.inc $(inc)\arena.inc $(inc)\intnat.inc $(inc)\mi.inc \ + $(inc)\filemode.inc $(inc)\error.inc $(inc)\syscall.inc + echo "touch dossym.inc; files that are in ..\inc" + +$(inc)\nibdos.obj: + cd ..\inc + $(make) + cd ..\dos + +$(inc)\const2.obj: + cd ..\inc + $(make) + cd ..\dos + +$(inc)\msdata.obj: + cd ..\inc + $(make) + cd ..\dos + +$(inc)\mstable.obj: + cd ..\inc + $(make) + cd ..\dos + +$(inc)\msdosme.obj: + cd ..\inc + $(make) + cd ..\dos + +msdisp.obj: msdisp.asm mssw.asm disp.asm \ + $(inc)\dossym.inc $(inc)\dosseg.asm + +mscode.obj: mscode.asm mssw.asm ms_code.asm \ + $(inc)\dossym.inc $(inc)\dosseg.asm $(inc)\devsym.inc + +time.obj: time.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc + +getset.obj: getset.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc + +parse.obj: parse.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc + +misc.obj: misc.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc $(inc)\bugtyp.asm + +misc2.obj: misc2.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\bugtyp.asm + +crit.obj: crit.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\bugtyp.asm + +cpmio.obj: cpmio.asm $(inc)\dosseg.asm \ + $(inc)\dossym.inc \ + $(inc)\devsym.inc \ + kstrin.asm strin.asm + +cpmio2.obj: cpmio2.asm $(inc)\dosseg.asm \ + $(inc)\dossym.inc $(inc)\devsym.inc + +fcbio.obj: fcbio.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc $(inc)\sf.inc $(inc)\fastopen.inc + +fcbio2.obj: fcbio2.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc + +search.obj: search.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc + +path.obj: path.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc + +ioctl.obj: ioctl.asm $(inc)\ioctl.inc $(inc)\dosseg.asm \ + $(inc)\dossym.inc $(inc)\devsym.inc + +delete.obj: delete.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc $(inc)\sf.inc $(inc)\fastxxxx.inc $(inc)\fastopen.inc + +rename.obj: rename.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc $(inc)\sf.inc + +finfo.obj: finfo.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc + +dup.obj: dup.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc + +create.obj: create.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc + +open.obj: open.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc $(inc)\fastopen.inc + +dinfo.obj: dinfo.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc $(inc)\bugtyp.asm $(inc)\buffer.inc + +isearch.obj: isearch.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc + +abort.obj: abort.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc $(inc)\sf.inc + +close.obj: close.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc $(inc)\buffer.inc + +dircall.obj: dircall.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc $(inc)\buffer.inc $(inc)\fastopen.inc + +disk.obj: disk.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc + +disk2.obj: disk2.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc $(inc)\buffer.inc + +disk3.obj: disk3.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc + +dir.obj: dir.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\buffer.inc $(inc)\fastopen.inc + +dir2.obj: dir2.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\buffer.inc $(inc)\fastopen.inc + +dev.obj: dev.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc + +mknode.obj: mknode.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc $(inc)\buffer.inc $(inc)\fastopen.inc \ + $(inc)\filemode.inc + +rom.obj: rom.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc $(inc)\buffer.inc + +fcb.obj: fcb.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc + +msctrlc.obj: msctrlc.asm mssw.asm ctrlc.asm \ + $(inc)\dosseg.asm $(inc)\dossym.inc $(inc)\devsym.inc \ + $(inc)\bugtyp.asm + +fat.obj: fat.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc $(inc)\buffer.inc $(inc)\curdir.inc + +buf.obj: buf.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc $(inc)\buffer.inc + +proc.obj: proc.asm \ + $(inc)\dosseg.asm $(inc)\dossym.inc $(inc)\devsym.inc \ + $(inc)\curdir.inc \ + exec.asm + +alloc.obj: alloc.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc + +srvcall.obj: srvcall.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc + +util.obj: util.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc + +macro.obj: macro.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc $(inc)\curdir.inc + +macro2.obj: macro2.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc $(inc)\curdir.inc + +handle.obj: handle.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc $(inc)\bugtyp.asm + +file.obj: file.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc $(inc)\bugtyp.asm $(inc)\fastopen.inc \ + $(inc)\filemode.inc + +lock.obj: lock.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc + +share.obj: share.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc + +extattr.obj: extattr.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc $(inc)\ea.inc $(inc)\buffer.inc + +ifs.obj: ifs.asm $(inc)\dosseg.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc $(inc)\doscntry.inc $(inc)\buffer.inc + +msdos.sys: msdos.cl1 $(inc)\nibdos.obj $(inc)\const2.obj \ + $(inc)\msdata.obj mscode.obj $(inc)\msdosme.obj time.obj getset.obj \ + parse.obj misc.obj misc2.obj crit.obj cpmio.obj cpmio2.obj \ + $(inc)\mstable.obj msdisp.obj fcbio.obj fcbio2.obj \ + search.obj path.obj ioctl.obj delete.obj rename.obj finfo.obj \ + dup.obj create.obj open.obj dinfo.obj isearch.obj buf.obj \ + abort.obj close.obj dircall.obj disk.obj disk2.obj disk3.obj dir.obj \ + dir2.obj dev.obj mknode.obj rom.obj fcb.obj msctrlc.obj fat.obj \ + proc.obj alloc.obj srvcall.obj util.obj macro.obj macro2.obj ifs.obj \ + handle.obj file.obj lock.obj share.obj extattr.obj \ + makefile msdos.lnk + link @msdos.lnk + exe2bin msdos.exe msdos.sys + del msdos.exe diff --git a/v4.0/src/DOS/MISC.ASM b/v4.0/src/DOS/MISC.ASM new file mode 100644 index 0000000..e169f32 --- /dev/null +++ b/v4.0/src/DOS/MISC.ASM @@ -0,0 +1,572 @@ +; SCCSID = @(#)misc.asm 1.1 85/04/10 +TITLE MISC - Miscellanious routines for MS-DOS +NAME MISC +; +; Miscellaneous system calls most of which are CAVEAT +; +; $SLEAZEFUNC +; $SLEAZEFUNCDL +; $GET_INDOS_FLAG +; $GET_IN_VARS +; $GET_DEFAULT_DPB +; $GET_DPB +; $DISK_RESET +; $SETDPB +; $Dup_PDB +; $CREATE_PROCESS_DATA_BLOCK +; SETMEM +; FETCHI_CHECK +; $GSetMediaID +; +; Revision history: +; +; Created: ARR 30 March 1983 +; +; A000 version 4.00 Jan. 1988 +; A001 D490 -- Change IOCTL subfunctions from 63h, 43h to 66h , 46h + +.xlist +; +; get the appropriate segment definitions +; +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +.cref +.list + +ENTRYPOINTSEG EQU 0CH +MAXDIF EQU 0FFFH +SAVEXIT EQU 10 + + i_need LASTBUFFER,DWORD + i_need BuffHead,DWORD + i_need INDOS,BYTE + i_need SYSINITVAR,BYTE + i_need CurrentPDB,WORD + i_need CreatePDB,BYTE + i_need FATBYTE,BYTE + i_need THISCDS,DWORD + i_need THISSFT,DWORD + i_need FETCHI_TAG,WORD ; for TAG CHECK + i_need BUF_HASH_COUNT,WORD ;AN000; number of Hash Entries + i_need HIGH_SECTOR,WORD ;AN000; high word of sector # + i_need DOS34_FLAG,WORD ;AN000; +if debug + I_need BugLev,WORD + I_need BugTyp,WORD +include bugtyp.asm +endif + +BREAK + +;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; +; C A V E A T P R O G R A M M E R ; +; ; +; Inputs: +; None +; Function: +; Return Stuff sort of like old get fat call +; Outputs: +; DS:BX = Points to FAT ID byte (IBM only) +; GOD help anyone who tries to do ANYTHING except +; READ this ONE byte. +; DX = Total Number of allocation units on disk +; CX = Sector size +; AL = Sectors per allocation unit +; = -1 if bad drive specified + + procedure $SLEAZEFUNC,NEAR +ASSUME DS:NOTHING,ES:NOTHING + + MOV DL,0 + +entry $SLEAZEFUNCDL +;Same as above except drive passed in DL (0=default, 1=A, 2=B, ...) + + context DS + MOV AL,DL + invoke GETTHISDRV ; Get CDS structure +SET_AL_RET: +; MOV AL,error_invalid_drive ; Assume error ;AC000; + JC BADSLDRIVE + invoke DISK_INFO + JC SET_AL_RET ; User FAILed to I 24 + MOV [FATBYTE],AH +; NOTE THAT A FIXED MEMORY CELL IS USED --> THIS CALL IS NOT +; RE-ENTRANT. USERS BETTER GET THE ID BYTE BEFORE THEY MAKE THE +; CALL AGAIN + MOV DI,OFFSET DOSGROUP:FATBYTE + XOR AH,AH ; AL has sectors/cluster + invoke get_user_stack +ASSUME DS:NOTHING + MOV [SI.user_CX],CX + MOV [SI.user_DX],BX + MOV [SI.user_BX],DI + MOV [SI.user_DS],CS ; stash correct pointer + return +BADSLDRIVE: + transfer FCB_Ret_ERR +EndProc $SLEAZEFUNC +; ; +; C A V E A T P R O G R A M M E R ; +;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; + +BREAK <$Get_INDOS_Flag -- Return location of DOS critical-section flag> +;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; +; C A V E A T P R O G R A M M E R ; +; ; +; Inputs: +; None +; Function: +; Returns location of DOS status for interrupt routines +; Returns: +; Flag location in ES:BX + + procedure $GET_INDOS_FLAG,NEAR +ASSUME DS:NOTHING,ES:NOTHING + + invoke get_user_stack + MOV [SI.user_BX],OFFSET DOSGROUP:INDOS + MOV [SI.user_ES],SS + return +EndProc $GET_INDOS_FLAG +; ; +; C A V E A T P R O G R A M M E R ; +;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; + +BREAK <$Get_IN_VARS -- Return a pointer to DOS variables> +;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; +; C A V E A T P R O G R A M M E R ; +; ; +; Return a pointer to interesting DOS variables This call is version +; dependent and is subject to change without notice in future versions. +; Use at risk. + procedure $GET_IN_VARS,NEAR + invoke get_user_stack + MOV [SI.user_BX],OFFSET DOSGROUP:SYSINITVAR + MOV [SI.user_ES],SS + return +EndProc $GET_IN_VARS +; ; +; C A V E A T P R O G R A M M E R ; +;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; + + +BREAK <$Get_Default_DPB,$Get_DPB -- Return pointer to DPB> +;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; +; C A V E A T P R O G R A M M E R ; +; ; +; Inputs: +; None +; Function: +; Return pointer to drive parameter table for default drive +; Returns: +; DS:BX points to the DPB +; AL = 0 If OK, = -1 if bad drive (call 50 only) + + procedure $GET_DEFAULT_DPB,NEAR +ASSUME DS:NOTHING,ES:NOTHING + + MOV DL,0 + + entry $GET_DPB +; Same as above only drive passed in DL (0=default, 1=A, 2=B, ...) + + context DS + MOV AL,DL + invoke GETTHISDRV ; Get CDS structure + JC ISNODRV ; no valid drive + LES DI,[THISCDS] ; check for net CDS + TEST ES:[DI.curdir_flags],curdir_isnet + JNZ ISNODRV ; No DPB to point at on NET stuff + EnterCrit CritDisk + invoke FATRead_CDS ; Force Media Check and return DPB + LeaveCrit CritDisk + JC ISNODRV ; User FAILed to I 24, only error we + ; have. + invoke get_user_stack +ASSUME DS:NOTHING + MOV [SI.user_BX],BP + MOV [SI.user_DS],ES + XOR AL,AL + return + +ISNODRV: + MOV AL,-1 + return +EndProc $GET_Default_dpb +; ; +; C A V E A T P R O G R A M M E R ; +;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; + + +BREAK <$Disk_Reset -- Flush out all dirty buffers> + + procedure $DISK_RESET,NEAR +ASSUME DS:NOTHING,ES:NOTHING + +; Inputs: +; None +; Function: +; Flush and invalidate all buffers +; Returns: +; Nothing + + MOV AL,-1 + entry $DISK_RESET2 + context DS + EnterCrit critDisk + OR [DOS34_FLAG],FROM_DISK_RESET ;AN000; + invoke FLUSHBUF + AND [DOS34_FLAG],NO_FROM_DISK_RESET ;AN000; +; +; We will "ignore" any errors on the flush, and go ahead and invalidate. This +; call doesn't return any errors and it is supposed to FORCE a known state, so +; let's do it. +; +; Invalidate 'last-buffer' used +; + MOV BX,-1 + MOV WORD PTR [LASTBUFFER+2],BX + MOV WORD PTR [LASTBUFFER],BX +; +; TEST [DOS34_FLAG],IFS_DRIVE_RESET ;AN000;;IFS. from ifs call back ? +; JZ FreeDone ;AN000;;IFS. no +; AND [DOS34_FLAG],NO_IFS_DRIVE_RESET ;AN000;;IFS. clear the flag +; LeaveCrit critDisk ;AN000;;IFS. +; return ;AN000;;IFS. return +FreeDone: + LeaveCrit critDisk + MOV AX,-1 + CallInstall NetFlushBuf,multNET,32 + return +EndProc $DISK_RESET + +BREAK <$SetDPB - Create a valid DPB from a user-specified BPB> +;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; +; C A V E A T P R O G R A M M E R ; +; ; + procedure $SETDPB,NEAR +ASSUME DS:NOTHING,ES:NOTHING + +; Inputs: +; ES:BP Points to DPB +; DS:SI Points to BPB +; Function: +; Build a correct DPB from the BPB +; Outputs: +; ES:BP and DS preserved all others destroyed + + MOV DI,BP + ADD DI,2 ; Skip over dpb_drive and dpb_UNIT + LODSW + STOSW ; dpb_sector_size + CMP BYTE PTR [SI.BPFTCNT-2],0 ; FAT file system drive ;AN000; + JNZ yesfat ; yes ;AN000; + MOV BYTE PTR ES:[DI.dpb_FAT_count-4],0 + JMP setend ; NO ;AN000; +yesfat: + MOV DX,AX + LODSB + DEC AL + STOSB ; dpb_cluster_mask + INC AL + XOR AH,AH +LOG2LOOP: + TEST AL,1 + JNZ SAVLOG + INC AH + SHR AL,1 + JMP SHORT LOG2LOOP +SAVLOG: + MOV AL,AH + STOSB ; dpb_cluster_shift + MOV BL,AL + MOVSW ; dpb_first_FAT Start of FAT (# of reserved sectors) + LODSB + STOSB ; dpb_FAT_count Number of FATs +; OR AL,AL ; NONFAT ? ;AN000; +; JZ setend ; yes, don't do anything ;AN000; + MOV BH,AL + LODSW + STOSW ; dpb_root_entries Number of directory entries + MOV CL,5 + SHR DX,CL ; Directory entries per sector + DEC AX + ADD AX,DX ; Cause Round Up + MOV CX,DX + XOR DX,DX + DIV CX + MOV CX,AX ; Number of directory sectors + INC DI + INC DI ; Skip dpb_first_sector + MOVSW ; Total number of sectors in DSKSIZ (temp as dpb_max_cluster) + LODSB + MOV ES:[BP.dpb_media],AL ; Media byte + LODSW ; Number of sectors in a FAT + STOSW ;AC000;;>32mb dpb_FAT_size + MOV DL,BH ;AN000;;>32mb + XOR DH,DH ;AN000;;>32mb + MUL DX ;AC000;;>32mb Space occupied by all FATs + ADD AX,ES:[BP.dpb_first_FAT] + STOSW ; dpb_dir_sector + ADD AX,CX ; Add number of directory sectors + MOV ES:[BP.dpb_first_sector],AX + + MOV CL,BL ;F.C. >32mb ;AN000; + CMP WORD PTR ES:[BP.DSKSIZ],0 ;F.C. >32mb ;AN000; + JNZ normal_dpb ;F.C. >32mb ;AN000; + XOR CH,CH ;F.C. >32mb ;AN000; + MOV BX,WORD PTR [SI+BPB_BigTotalSectors-BPB_SectorsPerTrack] ;AN000; + MOV DX,WORD PTR [SI+BPB_BigTotalSectors-BPB_SectorsPerTrack+2] ;AN000; + SUB BX,AX ;AN000;;F.C. >32mb + SBB DX,0 ;AN000;;F.C. >32mb + OR CX,CX ;AN000;;F.C. >32mb + JZ norot ;AN000;;F.C. >32mb +rott: ;AN000;;F.C. >32mb + CLC ;AN000;;F.C. >32mb + RCR DX,1 ;AN000;;F.C. >32mb + RCR BX,1 ;AN000;;F.C. >32mb + LOOP rott ;AN000;;F.C. >32mb +norot: ;AN000; + MOV AX,BX ;AN000;;F.C. >32mb + JMP setend ;AN000;;F.C. >32mb +normal_dpb: + SUB AX,ES:[BP.DSKSIZ] + NEG AX ; Sectors in data area +;; MOV CL,BL ; dpb_cluster_shift + SHR AX,CL ; Div by sectors/cluster +setend: + INC AX + MOV ES:[BP.dpb_max_cluster],AX + MOV ES:[BP.dpb_next_free],0 ; Init so first ALLOC starts at + ; begining of FAT + MOV ES:[BP.dpb_free_cnt],-1 ; current count is invalid. + return +EndProc $SETDPB +; ; +; C A V E A T P R O G R A M M E R ; +;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; + +BREAK <$Create_Process_Data_Block,SetMem -- Set up process data block> +;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; +; C A V E A T P R O G R A M M E R ; +; ; +; +; Inputs: DX is new segment address of process +; SI is end of new allocation block +; + procedure $Dup_PDB,NEAR +ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + MOV CreatePDB,0FFH ; indicate a new process + MOV DS,CurrentPDB + PUSH SI + JMP SHORT CreateCopy +EndProc $Dup_PDB + + procedure $CREATE_PROCESS_DATA_BLOCK,NEAR +ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + +; Inputs: +; DX = Segment number of new base +; Function: +; Set up program base and copy term and ^C from int area +; Returns: +; None +; Called at DOS init + + CALL get_user_stack + MOV DS,[SI.user_CS] + PUSH DS:[PDB_Block_len] +CreateCopy: + MOV ES,DX + XOR SI,SI ; copy all 80h bytes + MOV DI,SI + MOV CX,80H + REP MOVSW +; DOS 3.3 7/9/86 + + MOV CX,FilPerProc ; copy handles in case of + MOV DI,PDB_JFN_Table ; Set Handle Count has been issued + PUSH DS + LDS SI,DS:[PDB_JFN_Pointer] + REP MOVSB + POP DS + +; DOS 3.3 7/9/86 + TEST CreatePDB,0FFh ; Shall we create a process? + JZ Create_PDB_cont ; nope, old style call +; +; Here we set up for a new process... +; + + PUSH CS ; Called at DOSINIT time, NO SS + POP DS + DOSAssume CS,,"MISC/Create_Copy" + XOR BX,BX ; dup all jfns + MOV CX,FilPerProc ; only 20 of them + +Create_dup_jfn: + PUSH ES ; save new PDB + invoke SFFromHandle ; get sf pointer + MOV AL,-1 ; unassigned JFN + JC CreateStash ; file was not really open + TEST ES:[DI].sf_flags,sf_no_inherit + JNZ CreateStash ; if no-inherit bit is set, skip dup. +; +; We do not inherit network file handles. +; + MOV AH,BYTE PTR ES:[DI].sf_mode + AND AH,sharing_mask + CMP AH,sharing_net_fcb + jz CreateStash +; +; The handle we have found is duplicatable (and inheritable). Perform +; duplication operation. +; + MOV WORD PTR [THISSFT],DI + MOV WORD PTR [THISSFT+2],ES + invoke DOS_DUP ; signal duplication +; +; get the old sfn for copy +; + invoke pJFNFromHandle ; ES:DI is jfn + MOV AL,ES:[DI] ; get sfn +; +; Take AL (old sfn or -1) and stash it into the new position +; +CreateStash: + POP ES + MOV ES:[BX].PDB_JFN_Table,AL; copy into new place! + INC BX ; next jfn... + LOOP create_dup_jfn + + MOV BX,CurrentPDB ; get current process + MOV ES:[PDB_Parent_PID],BX ; stash in child + MOV [CurrentPDB],ES + ASSUME DS:NOTHING + MOV DS,BX +; +; end of new process create +; +Create_PDB_cont: + MOV BYTE PTR [CreatePDB],0h ; reset flag + POP AX + + entry SETMEM +ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + +; Inputs: +; AX = Size of memory in paragraphs +; DX = Segment +; Function: +; Completely prepares a program base at the +; specified segment. +; Called at DOS init +; Outputs: +; DS = DX +; ES = DX +; [0] has INT int_abort +; [2] = First unavailable segment +; [5] to [9] form a long call to the entry point +; [10] to [13] have exit address (from int_terminate) +; [14] to [17] have ctrl-C exit address (from int_ctrl_c) +; [18] to [21] have fatal error address (from int_fatal_abort) +; DX,BP unchanged. All other registers destroyed. + + XOR CX,CX + MOV DS,CX + MOV ES,DX + MOV SI,addr_int_terminate + MOV DI,SAVEXIT + MOV CX,6 + REP MOVSW + MOV ES:[2],AX + SUB AX,DX + CMP AX,MAXDIF + JBE HAVDIF + MOV AX,MAXDIF +HAVDIF: + SUB AX,10H ; Allow for 100h byte "stack" + MOV BX,ENTRYPOINTSEG ; in .COM files + SUB BX,AX + MOV CL,4 + SHL AX,CL + MOV DS,DX + MOV WORD PTR DS:[PDB_CPM_Call+1],AX + MOV WORD PTR DS:[PDB_CPM_Call+3],BX + MOV DS:[PDB_Exit_Call],(int_abort SHL 8) + mi_INT + MOV BYTE PTR DS:[PDB_CPM_Call],mi_Long_CALL + MOV WORD PTR DS:[PDB_Call_System],(int_command SHL 8) + mi_INT + MOV BYTE PTR DS:[PDB_Call_System+2],mi_Long_RET + MOV WORD PTR DS:[PDB_JFN_Pointer],PDB_JFN_Table + MOV WORD PTR DS:[PDB_JFN_Pointer+2],DS + MOV WORD PTR DS:[PDB_JFN_Length],FilPerProc +; +; The server runs several PDB's without creating them VIA EXEC. We need to +; enumerate all PDB's at CPS time in order to find all references to a +; particular SFT. We perform this by requiring that the server link together +; for us all sub-PDB's that he creates. The requirement for us, now, is to +; initialize this pointer. +; + MOV word ptr DS:[PDB_Next_PDB],-1 + MOV word ptr DS:[PDB_Next_PDB+2],-1 + return + +EndProc $CREATE_PROCESS_DATA_BLOCK + +; ; +; C A V E A T P R O G R A M M E R ; +;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; + procedure FETCHI_CHECK,NEAR +ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + PUSHF + CMP CS:[FETCHI_TAG],22642 + JZ TAG_OK + invoke DOSINIT ; go to hell +TAG_OK: + POPF + return +EndProc FETCHI_CHECK + +BREAK <$GSetMediaID -- get set media ID> +; Inputs: +; BL= drive number as defined in IOCTL +; AL= 0 get media ID +; 1 set media ID +; DS:DX= buffer containing information +; DW 0 info level (set on input) +; DD ? serial # +; DB 11 dup(?) volume id +; DB 8 dup(?) file system type +; Function: +; Get or set media ID +; Returns: +; carry clear, DS:DX is filled +; carry set, error + + procedure $GSetMediaID,NEAR ;AN000; +ASSUME DS:NOTHING,ES:NOTHING ;AN000; + + MOV CX,0866H ;AN000;MS.; assume get for IOCTL + CMP AL,0 ;AN001;MS.; get ? + JZ doioctl ;AN000;MS.; yes + CMP AL,1 ;AN000;MS.; set ? + JNZ errorfunc ;AN000;MS.; no + MOV CX,0846H ;AN001;MS.; +doioctl: ;AN000; + MOV AL,0DH ;AN000;MS.; generic IOCTL + invoke $IOCTL ;AN000;MS.; let IOCTL take care of it + return ;AN000;MS.; +errorfunc: ;AN000; + error error_invalid_function;AN000;MS. ; invalid function +EndProc $GSetMediaID ;AN000; + +CODE ENDS +END diff --git a/v4.0/src/DOS/MISC2.ASM b/v4.0/src/DOS/MISC2.ASM new file mode 100644 index 0000000..c8860bb --- /dev/null +++ b/v4.0/src/DOS/MISC2.ASM @@ -0,0 +1,594 @@ +; SCCSID = @(#)misc2.asm 1.1 85/04/10 +TITLE MISC2 - Miscellanious routines for MS-DOS +NAME MISC2 +; +; Miscellaneous useful routines +; +; StrCpy +; StrCmp +; Ucase +; StrLen +; DStrLen +; Idle +; TableDispatch +; FastInit ; DOS 4.0 +; FastRet ; DOS 4.0 +; NLS_OPEN ; DOS 4.0 +; NLS_LSEEK ; DOS 4.0 +; Fake_User_Stack ; DOS 4.0 +; GetDevList ; DOS 4.0 +; NLS_IOCTL ; DOS 4.0 +; NLS_GETEXT ; DOS 4.0 +; MSG_RETRIEVAL ; DOS 4.0 +; Fake_Version ; DOS 4.0 +; +; Revision history: +; +; Created: ARR 30 March 1983 +; +; A000 version 4.0 Jan. 1988 +; A001 DCR 486 - Share installation for >32mb drives +; A006 DCR 503 - fake version number for IBMCACHE + +.xlist +; +; get the appropriate segment definitions +; +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +include dossym.inc +include fastseek.inc ;AN000; +include fastxxxx.inc ;AN000; +.cref +.list + + i_need THISCDS,DWORD + I_Need RetryLoop,WORD + I_need fSharing,BYTE ; TRUE => server-issued call + I_need FastTable,BYTE ;AN000; + I_need FastFlg,BYTE ;AN000; + I_need User_SP_2F,WORD ;AN000; + I_need User_SP,WORD ;AN000; + I_need User_SS,WORD ;AN000; + I_need SysInitTable,BYTE ;AN000; + I_need EXTERR,WORD ;AN000; + I_need MSG_EXTERROR,DWORD ;AN000; + I_need fshare,byte ;AN001; + I_need Special_version,WORD ;AN006; +if debug + I_need BugLev,WORD + I_need BugTyp,WORD +include bugtyp.asm +endif + +Break + +; +; Strcmp - compare ASCIZ DS:SI to ES:DI. Case INSENSITIVE. '/' = '\' +; Strings of different lengths don't match. +; Inputs: DS:SI - pointer to source string ES:DI - pointer to dest string +; Outputs: Z if strings same, NZ if different +; Registers modified: NONE + +Procedure StrCmp,NEAR + ASSUME CS:DOSGroup,SS:DOSGroup,DS:NOTHING,ES:NOTHING + SaveReg +Cmplp: + LODSB + IF DBCS ;AN000; + invoke testkanj ;AN000;; 2/13/KK + jz notkanj1 ;AN000;; 2/13/KK + dec si ;AN000;; Do source again 2/13/KK + cmpsb ;AN000;; First byte 2/13/KK + JNZ PopRet ;AN000;; Strings dif 2/13/KK + cmpsb ;AN000;; Second byte of kanji char 2/13/KK + JNZ PopRet ;AN000;; Strings dif 2/13/KK + mov al,byte ptr [SI-1] ;AN000;; Need last byte in AL 2/13/KK + jmp short Tend ;AN000; +notkanj1: ;AN000;; 2/13/KK + ENDIF ;AN000; + CALL uCase ; convert to upper case + Invoke PathChrCmp ; convert / to \ + MOV AH,AL + MOV AL,ES:[DI] + INC DI + CALL uCase ; convert to upper case + Invoke PathChrCmp ; convert / to \ + CMP AH,AL + JNZ PopRet ; Strings dif +Tend: + OR AL,AL + JNZ Cmplp ; More string +PopRet: + RestoreReg + return +EndProc StrCmp + +Break + +; +; Strcpy - copy an ASCIZ string from DS:SI to ES:DI and make uppercase +; FStrcpy - copy an ASCIZ string from DS:SI to ES:DI. no modification of +; characters. +; +; Inputs: DS:SI - pointer to source string +; ES:DI - pointer to destination string +; Outputs: ES:DI point byte after nul byte at end of dest string +; DS:SI point byte after nul byte at end of source string +; Registers modified: SI,DI + +Procedure StrCpy,NEAR + ASSUME CS:DOSGroup,SS:DOSGroup,DS:NOTHING,ES:NOTHING + SaveReg +CPYLoop: + LODSB + IF DBCS ;AN000; + invoke testkanj ;AN000;; 2/13/KK + jz notkanj2 ;AN000;; 2/13/KK + STOSB ;AN000;; 2/13/KK + LODSB ;AN000;; 2/13/KK + STOSB ;AN000;; 2/13/KK + jmp short CPYLoop ;AN000;; 3/31/KK + +notkanj2: ;AN000;; 2/13/KK + ENDIF ;AN000; + CALL uCase ; convert to upper case + Invoke PathChrCmp ; convert / to \ + STOSB +Tend2: + OR AL,AL + JNZ CPYLoop + RestoreReg + return +EndProc StrCpy + +Procedure FStrCpy,NEAR + ASSUME CS:DOSGroup,SS:DOSGroup,DS:NOTHING,ES:NOTHING + SaveReg +FCPYLoop: + LODSB + STOSB + OR AL,AL + JNZ FCPYLoop + RestoreReg + return +EndProc FStrCpy + +; +; Upper case the letter in AL. Most chars are non lowercase. +; +Procedure uCase,NEAR +; CMP AL,'a' +; JAE Maybe +; return +;Maybe: +; CMP AL,'z' +; JA CaseRet +; ADD AL,'A'-'a' +;CaseRet: +;;; 10/31/86 let's do file upper case for all DOS file names + invoke GetLet2 +;;; 10/31/86 let's do file upper case for all DOS file names + return +EndProc uCase + +Break + +; +; StrLen - Compute length of string ES:DI +; Inputs: ES:DI - pointer to string +; Outputs: CX is size of string INCLUDING the NUL +; Registers modified: CX + +Procedure StrLen,NEAR + ASSUME CS:DOSGroup,SS:DOSGroup,DS:NOTHING,ES:NOTHING + PUSH DI + PUSH AX + MOV CX,-1 + XOR AL,AL + REPNE SCASB + NOT CX + POP AX + POP DI + return +EndProc StrLen + +; +; DStrLen - Compute length of string DS:SI +; Inputs: DS:SI - pointer to string +; Outputs: CX is size of string INCLUDING the NUL +; Registers modified: CX +Procedure DStrLen,NEAR + CALL XCHGP + CALL StrLen + CALL XCHGP + return +EndProc DStrLen + +Break + +Procedure XCHGP,NEAR + SaveReg + RestoreReg + XCHG SI,DI + return +EndProc XCHGP + +Break + +; +; Idle - when retrying an operation due to a lock/sharing violation, we spin +; until RetryLoop is exhausted. +; +; Inputs: RetryLoop is the number of times we spin +; Outputs: Wait +; Registers modified: none + +Procedure Idle,NEAR + ASSUME CS:DOSGroup,SS:DOSGROUP,DS:NOTHING,ES:NOTHING + TEST fSharing,-1 + retnz + SaveReg + MOV CX,RetryLoop + JCXZ Idle3 +Idle1: PUSH CX + XOR CX,CX +Idle2: LOOP Idle2 + POP CX + LOOP Idle1 +Idle3: RestoreReg + return +EndProc Idle + +Break + +; +; TableDispatch - given a table and an index, jmp to the approptiate +; routine. Preserve all input registers to the routine. +; +; Inputs: Push return address +; Push Table address +; Push index (byte) +; Outputs: appropriate routine gets jumped to. +; return indicates invalid index +; Registers modified: none. + +TableFrame STRUC +OldBP DW ? +OldRet DW ? +Index DB ? +Pad DB ? +Tab DW ? +NewRet DW ? +TableFrame ENDS + +procedure TableDispatch,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,SS:NOTHING,SS:NOTHING + PUSH BP + MOV BP,SP + PUSH BX ; save BX + MOV BX,[BP.Tab] ; get pointer to table + MOV BL,CS:[BX] ; maximum index + CMP [BP.Index],BL ; table error? + JAE TableError ; yes + MOV BL,[BP.Index] ; get desired table index + XOR BH,BH ; convert to word + SHL BX,1 ; convert to word pointer + INC BX ; point past first length byte + ADD BX,[BP.Tab] ; get real offset + MOV BX,CS:[BX] ; get contents of table entry + MOV [BP.Tab],BX ; put table entry into return address + POP BX ; restore BX + POP BP ; restore BP + ADD SP,4 ; clean off Index and our return addr + return ; do operation +TableError: + POP BX ; restore BX + POP BP ; restore BP + RET 6 ; clean off Index, Table and RetAddr +EndProc TableDispatch + +Break + +; +; TestNet - examine CDS pointed to by ThisCDS and see if it indicates a +; network CDS. This will handle NULL cds also. +; +; Inputs: ThisCDS points to CDS or NULL +; Outputs: ES:DI = ThisCDS +; carry Set => network +; carry Clear => local +; Registers modified: none. + +Procedure TestNet,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING + LES DI,ThisCDS + CMP DI,-1 + JZ CMCRet ; UNC? carry is clear + TEST ES:[DI].curdir_flags,curdir_isnet + JNZ CMCret ; jump has carry clear + return ; carry is clear +CMCRet: CMC + return + +EndProc TestNet + +Break + +; +; IsSFTNet - examine SF pointed to by ES:DI and see if it indicates a +; network file. +; +; Inputs: ES:DI point to SFT +; Outputs: Zero set if not network sft +; zero reset otherwise +; Carry CLEAR!!! +; Registers modified: none. + +Procedure IsSFTNet,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING + TEST ES:[DI].sf_flags,sf_isnet + return +EndProc IsSFTNet + +Break + +; DOS 4.00 2/9/87 +; FastInit - initialize the FASTXXX routine entry +; in the FastTable +; +; Inputs: BX = FASTXXX ID ( 1=fastopen, 2=fastseek,,,,) +; DS:SI = address of FASTXXX routine entry +; SI = -1 for query only +; Outputs: Carry flag clear, if success +; Carry flag set, if failure +; +; + +Procedure FastInit,NEAR ;AN000; + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING ;AN000; + + MOV DI,OFFSET DOSGROUP:FastTable + 2 ;AN000;FO. points to fastxxx entry + DEC BX ;AN000;FO.;; decrement index + MOV DX,BX ;AN000;FO.;; save bx + SHL BX,1 ;AN000;FO.;; times 4 , each entry is DWORD + SHL BX,1 ;AN000;FO. + ADD DI,BX ;AN000;FO. index to the entry + MOV AX,WORD PTR CS:[DI+2] ;AN000;FO. get entry segment +fcheck: ;AN000; + MOV CX,CS ;AN000;FO.;; get DOS segment + CMP AX,CX ;AN000;FO.;; first time installed ? + JZ ok_install ;AN000;FO.;; yes + OR AX,AX ;AN000;FO.; + JZ ok_install ;AN000;FO.; + STC ;AN000;FO.;; already installed ! + JMP SHORT FSret ;AN000;FO. set carry +ok_install: ;AN000; + CMP SI,-1 ;AN000;FO.; Query only ? + JZ FSret ;AN000;FO.; yes + MOV CX,DS ;AN000;FO.; get FASTXXX entry segment + MOV CX,DS ;AN000;FO.;; get FASTXXX entry segment + MOV WORD PTR CS:[DI+2],CX ;AN000;FO.;; initialize routine entry + MOV WORD PTR CS:[DI],SI ;AN000;FO.;; initialize routine offset + MOV DI,OFFSET DOSGROUP:FastFlg ;AN000;FO.; get addr of FASTXXX flags + ADD DI,DX ;AN000;FO.; index to a FASTXXX flag + OR byte ptr CS:[DI],Fast_yes ;AN000;FO.; indicate installed + +FSret: ;AN000; + return ;AN000;FO. +EndProc FastInit ;AN000;FO. + +Break + +; DOS 3.3 6/10/86 +; FastRet - indicate FASTXXXX not in memory +; +; Inputs: None +; Outputs: AX = -1 and carry flag set +; +; Registers modified: none. + +Procedure FastRet,FAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING + MOV AX,-1 + STC + RET +EndProc FastRet + +Break + +; DOS 3.3 6/10/86 +; NLS_OPEN - call $OPEN for NLSFUNC +; +; Inputs: Same input as $OPEN except CL = mode +; Outputs: same output as $OPEN +; + +Procedure NLS_OPEN,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING + +; MOV BL,[CPSWFLAG] ; disable code page matching logic +; MOV [CPSWFLAG],0 +; PUSH BX ; save current state + + MOV AL,CL ; set up correct interface for $OPEN + invoke $OPEN + + ; POP BX ; restore current state + ; MOV [CPSWFLAG],BL + RET +EndProc NLS_OPEN + +Break + +; DOS 3.3 6/10/86 +; NLS_LSEEK - call $LSEEK for NLSFUNC +; +; Inputs: BP = open mode +; Outputs: same output as $LSEEK +; + +Procedure NLS_LSEEK,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING + + PUSH [user_SP] ; save user stack + PUSH [user_SS] + CALL Fake_User_Stack + MOV AX,BP ; set up correct interface for $LSEEK + invoke $LSEEK + POP [user_SS] ; restore user stack + POP [user_SP] + RET +EndProc NLS_LSEEK + + +Break + + +; DOS 3.3 6/10/86 +; Fake_User_Stack - save user stack pointer +; + +Procedure Fake_User_Stack,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING + + MOV AX,[User_SP_2F] ; replace with INT 2F stack + MOV [user_SP],AX + + MOV AX,CS + MOV [user_SS],AX ; DOSGROUP + + RET +EndProc Fake_User_Stack + +; +Break + + +; DOS 3.3 7/25/86 +; GetDevList - get device header list pointer +; +; Output: AX:BX points to the device header list + +Procedure GetDevList,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGROUP + + MOV SI,OFFSET DOSGROUP:SysInitTable + LDS SI,CS:[SI.SYSI_InitVars] + + MOV AX,WORD PTR DS:[SI.SYSI_DEV] + MOV BX,WORD PTR DS:[SI.SYSI_DEV+2] + + RET +EndProc GetDevList + +Break + +; DOS 3.3 7/25/86 +; NLS_IOCTL - call $IOCTL for NLSFUNC +; +; Inputs: BP = function code 0CH +; Outputs: same output as generic $IOCTL +; + +Procedure NLS_IOCTL,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING + + PUSH [user_SP] ; save user stack + PUSH [user_SS] + CALL Fake_User_Stack + MOV AX,BP ; set up correct interface for $LSEEK + invoke $IOCTL + POP [user_SS] ; restore user stack + POP [user_SP] + RET +EndProc NLS_IOCTL + +Break + +; DOS 3.3 7/25/86 +; NLS_GETEXT - +; +; Inputs: none +; Outputs: AX = extended error +; + +Procedure NLS_GETEXT,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING + + MOV AX,CS:[EXTERR] ; return extended error + RET +EndProc NLS_GETEXT + +Break + +; DOS 4.00 +; +; Inputs: DL=0 get extended error message addr +; =1 set extended error message addr +; =2 get parser error message addr +; =3 set parser error message addr +; =4 get critical error message addr +; =5 set critical error message addr +; =6 get file system error message addr +; =7 set file system error message addr +; =8 get address for code reduction +; =9 set address for code reduction +; Function: get/set message address +; Outputs: ES:DI points to addr when get +; + +Procedure MSG_RETRIEVAL,NEAR ;AN000; + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING ;AN000; + + PUSH AX ;AN000;;MS. save regs + PUSH SI ;AN000;;MS. save regs + MOV AX,DX ;AN000;;MS. + MOV SI,OFFSET DOSGROUP:MSG_EXTERROR ;AN000;;MS. + TEST AL,1 ;AN000;;MS. get ? + JZ toget ;AN000;;MS. yes + DEC AL ;AN000;;MS. +toget: ;AN000; + SHL AL,1 ;AN000;;MS. times 2 + XOR AH,AH ;AN000;;MS. + ADD SI,AX ;AN000;;MS. position to the entry + TEST DL,1 ;AN000;;MS. get ? + JZ getget ;AN000;;MS. yes + MOV WORD PTR CS:[SI],DI ;AN000;;MS. set MSG + MOV WORD PTR CS:[SI+2],ES ;AN000;;MS. address to ES:DI + JMP SHORT MSGret ;AN000;;MS. exit +getget: ;AN000; + LES DI,DWORD PTR CS:[SI] ;AN000;;MS. get msg addr +MSGret: ;AN000; + POP SI ;AN000;;MS. + POP AX ;AN000;;MS. + return ;AN000;;MS. exit + +EndProc MSG_RETRIEVAL ;AN000; + + +Break + +; +; Inputs: DL=0 current version number +; <>0 special version number +; Function: set special version number +; Outputs: version number is changed +; + +Procedure Fake_version,NEAR ;AN000; + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING ;AN000; + + MOV [Special_version],DX ;AN006;MS. + return ;AN006;;MS. exit + +EndProc Fake_version ;AN006;;MS. + + + +CODE ENDS + END diff --git a/v4.0/src/DOS/MKNODE.ASM b/v4.0/src/DOS/MKNODE.ASM new file mode 100644 index 0000000..968c8eb --- /dev/null +++ b/v4.0/src/DOS/MKNODE.ASM @@ -0,0 +1,890 @@ +; SCCSID = @(#)mknode.asm 1.5 85/08/29 +TITLE MKNODE - Node maker +NAME MKNODE +; Low level routines for making a new local file system node +; and filling in an SFT from a directory entry +; +; BUILDDIR +; SETDOTENT +; MakeNode +; NEWENTRY +; FREEENT +; NEWDIR +; DOOPEN +; RENAME_MAKE +; CHECK_VIRT_OPEN +; +; Revision history: +; +; AN000 version 4.0 Jan. 1988 +; A004 PTM 3680 --- Make SFT NAME field offset same as 3.30 + +; +; get the appropriate segment definitions +; +.xlist +include dosseg.asm +include fastopen.inc + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +include dossym.inc +include devsym.inc +.cref +.list + + i_need EntFree,WORD + i_need DirStart,WORD + i_need LastEnt,WORD + i_need ClusNum,WORD + i_need CurBuf,DWORD + i_need Attrib,BYTE + i_need VolID,BYTE + i_need Name1,BYTE + i_need ThisDPB,DWORD + i_need EntLast,WORD + i_need Creating,BYTE + i_need SecClusPos,BYTE + i_need ClusFac,BYTE + i_need NxtClusNum,WORD + i_need DirSec,WORD + i_need NoSetDir,BYTE + i_need THISSFT,DWORD + i_need SATTRIB,BYTE + i_need ALLOWED,BYTE + i_need FAILERR,BYTE + i_need VIRTUAL_OPEN + I_need FastOpen_Ext_info,BYTE ; DOS 3.3 + I_need FastOpenFlg,BYTE ; DOS 3.3 + I_need CPSWFLAG,BYTE ;FT. DOS 3.4 ;AN000; + I_need EXTOPEN_ON,BYTE ;FT. DOS 3.4 ;AN000; + I_need EXTOPEN_FLAG,WORD ;FT. DOS 3.4 ;AN000; + I_need EXTOPEN_IO_MODE,WORD ;FT. DOS 3.4 ;AN000; + I_need HIGH_SECTOR,WORD ;>32mb ;AN000; + I_need ACT_PAGE,WORD ;>32mb ;AN000; + +Break + +; Inputs: +; ES:BP Points to DPB +; [THISSFT] Set if using NEWDIR entry point +; (used by ALLOCATE) +; [LASTENT] current last valid entry number in directory if no free +; entries +; [DIRSTART] Points to first cluster of dir (0 means root) +; Function: +; Grow directory if no free entries and not root +; Outputs: +; CARRY SET IF FAILURE +; ELSE +; AX entry number of new entry +; If a new dir [DIRSTART],[CLUSFAC],[CLUSNUM],[DIRSEC] set +; AX = first entry of new dir +; GETENT should be called to set [LASTENT] + + procedure BUILDDIR,NEAR + DOSAssume CS,,"BuildDir" + ASSUME ES:NOTHING + + MOV AX,[ENTFREE] + CMP AX,-1 + JZ CHECK_IF_ROOT + CLC + return + +CHECK_IF_ROOT: + CMP [DIRSTART],0 + JNZ NEWDIR + STC + return ; Can't grow root + + entry NEWDIR + MOV BX,[DIRSTART] + OR BX,BX + JZ NULLDIR + invoke GETEOF + retc ; Screw up +NULLDIR: + MOV CX,1 + invoke ALLOCATE + retc + MOV DX,[DIRSTART] + OR DX,DX + JNZ ADDINGDIR + invoke SETDIRSRCH + retc + MOV [LASTENT],-1 + JMP SHORT GOTDIRREC +ADDINGDIR: + PUSH BX + MOV BX,[ClusNum] + Invoke IsEof + POP BX + JB NOTFIRSTGROW +;;;; 10/17/86 update CLUSNUM in the fastopen cache + MOV [CLUSNUM],BX + PUSH CX + PUSH AX + PUSH BP + MOV AH,1 ; CLUSNUM update + MOV DL,ES:[BP.dpb_drive] ; drive # + MOV CX,[DIRSTART] ; first cluster # + MOV BP,BX ; CLUSNUM + invoke FastOpen_Update + POP BP + POP AX + POP CX + +;;;; 10/17/86 update CLUSNUM in the fastopen cache +NOTFIRSTGROW: + MOV DX,BX + XOR BL,BL + invoke FIGREC +GOTDIRREC: + MOV CL,ES:[BP.dpb_cluster_mask] + INC CL + XOR CH,CH +ZERODIR: + PUSH CX + MOV [ALLOWED],allowed_FAIL + allowed_RETRY + MOV AL,0FFH + invoke GETBUFFR + JNC GET_SSIZE + POP CX + return + +GET_SSIZE: + MOV CX,ES:[BP.dpb_sector_size] + PUSH ES + LES DI,[CURBUF] + OR ES:[DI.buf_flags],buf_isDIR + PUSH DI + ADD DI,BUFINSIZ + XOR AX,AX + SHR CX,1 + REP STOSW + JNC EVENZ + STOSB +EVENZ: + POP DI + + TEST ES:[DI.buf_flags],buf_dirty ;LB. if already dirty ;AN000; + JNZ yesdirty ;LB. don't increment dirty count ;AN000; + invoke INC_DIRTY_COUNT ;LB. ;AN000; + OR ES:[DI.buf_flags],buf_dirty +yesdirty: + POP ES + POP CX + INC DX + LOOP ZERODIR + MOV AX,[LASTENT] + INC AX + CLC + return + +EndProc BUILDDIR + +; +; set up a . or .. directory entry for a directory. +; +; Inputs: ES:DI point to the beginning of a directory entry. +; AX contains ". " or ".." +; DX contains first cluster of entry +; + procedure SETDOTENT,NEAR + DOSAssume CS,,"SetDotEnt" +; +; Fill in name field +; + STOSW + MOV CX,4 + MOV AX," " + REP STOSW + STOSB +; +; Set up attribute +; + MOV AL,attr_directory + errnz dir_attr-(dir_name+11) + STOSB +; +; Initialize time and date of creation +; + ADD DI,10 + MOV SI,WORD PTR [THISSFT] + MOV AX,[SI.sf_time] + errnz dir_time-(dir_attr+1+10) + STOSW + MOV AX,[SI.sf_date] + errnz dir_date-(dir_time+2) + STOSW +; +; Set up first cluster field +; + MOV AX,DX + errnz dir_first-(dir_date+2) + STOSW +; +; 0 file size +; + XOR AX,AX + errnz dir_size_l-(dir_first+2) + STOSW + STOSW + errnz <(size dir_entry)-(dir_size_l+4)> + return +EndProc SETDOTENT + +Break + +; Inputs: +; AL - attribute to create +; AH = 0 if it is ok to truncate a file already by this name +; AH = Non 0 if this is an error +; (AH ignored on dirs and devices) +; NOTE: When making a DIR or volume ID, AH need not be set since +; a name already existant is ALWAYS an error in these cases. +; [WFP_START] Points to WFP string ("d:/" must be first 3 chars, NUL +; terminated) +; [CURR_DIR_END] Points to end of Current dir part of string +; ( = -1 if current dir not involved, else +; Points to first char after last "/" of current dir part) +; [THISCDS] Points to CDS being used +; [THISSFT] Points to an empty SFT. EXCEPT sf_mode filled in. +; Function: +; Make a new node +; Outputs: +; Sets EXTERR_LOCUS = errLOC_Disk or errLOC_Unk via GetPathNoset +; CARRY SET IF ERROR +; AX = 1 A node by this name exists and is a directory +; AX = 2 A new node could not be created +; AX = 3 A node by this name exists and is a disk file +; (AH was NZ on input) +; AX = 4 Bad Path +; SI return from GetPath maintained +; AX = 5 Attribute mismatch +; AX = 6 Sharing Violation +; (INT 24 generated ALWAYS since create is always compat mode +; AX = 7 file not found for Extended Open (not exists and fails) +; ELSE +; AX = 0 Disk Node +; AX = 3 Device Node (error in some cases) +; [DIRSTART],[DIRSEC],[CLUSFAC],[CLUSNUM] set to directory +; containing new node. +; [CURBUF+2]:BX Points to entry +; [CURBUF+2]:SI Points to entry.dir_first +; [THISSFT] is filled in +; sf_mode = unchanged. +; Attribute byte in entry is input AL +; DS preserved, others destroyed + + procedure MakeNode,NEAR + DOSAssume CS,,"MakeNode" + ASSUME ES:NOTHING + + MOV WORD PTR [CREATING],0E5FFH ; Creating, not DEL *.* + PUSH AX ; Save AH value + MOV [NoSetDir],0 + MOV [SATTRIB],AL + invoke GetPathNoSet + MOV DL,CL ; Save CL info + MOV CX,AX ; Device ID to CH + POP AX ; Get back AH + JNC make_exists ; File existed + JNZ make_err_4 ; Path bad + CMP DL,80H ; Check "CL" return from GETPATH + JZ make_type ; Name simply not found, and no metas +make_err_4: + MOV AL,4 ; case 1 bad path +make_err_ret: + XOR AH,AH + STC + return + + entry RENAME_MAKE ; Used by DOS_RENAME to "copy" a node + +make_type: +;Extended Open hooks + TEST [EXTOPEN_ON],ext_open_on ;FT. from extended open ;AN000; + JZ make_type2 ;FT. no ;AN000; + OR [EXTOPEN_ON],ext_file_not_exists ;FT. set for extended open ;AN000; + TEST [EXTOPEN_FLAG],0F0H ;FT. not exists and fails ;AN000; + JNZ make_type2 ;FT. no ;AN000; + STC ;FT. set carry ;AN000; + MOV AX,7 ;FT. file not found ;AN000; + return ;FT. ;AN000; +make_type2: +;Extended Open hooks + LES DI,[THISSFT] +; MOV ES:[DI.sf_mode],sharing_compat + open_for_both + XOR AX,AX ; nothing exists Disk Node + STC ; Not found + JMP make_new + +; +; The node exists. It may be either a device, directory or file: +; Zero set => directory +; High bit of CH on => device +; else => file +make_exists: + JZ make_exists_dir + MOV AL,3 ; file exists type 3 (error or device node) + TEST BYTE PTR [ATTRIB],(attr_volume_id+attr_directory) + JNZ make_err_ret_5 ; Cannot already exist as Disk or Device Node + ; if making DIR or Volume ID + OR CH,CH + JS make_share ; No further checks on attributes if device + OR AH,AH + JNZ make_err_ret ; truncating NOT OK (AL = 3) + PUSH CX ; Save device ID + MOV ES,WORD PTR [CURBUF+2] + MOV CH,ES:[BX+dir_attr] ; Get file attributes + TEST CH,attr_read_only + JNZ make_err_ret_5P ; Cannot create on read only files + invoke MatchAttributes + POP CX ; Devid back in CH + JNZ make_err_ret_5 ; Attributes not ok + XOR AL,AL ; AL = 0, Disk Node +make_share: + XOR AH,AH + PUSH AX ; Save Disk or Device node + PUSH CX ; Save Device ID + MOV AH,CH ; Device ID to AH + CALL DOOPEN ; Fill in SFT for share check + LES DI,[THISSFT] +; MOV ES:[DI.sf_mode],sharing_compat + open_for_both + SaveReg ; Save CURBUF pointers + invoke ShareEnter + jnc MakeEndShare +; +; User failed request. +; + RestoreReg +Make_Share_ret: + MOV AL,6 + JMP make_err_ret + +make_err_ret_5P: + POP CX ; Get back device ID +make_err_ret_5: + MOV AL,5 ; Attribute mismatch + JMP make_err_ret + +make_exists_dir: + MOV AL,1 ; exists as directory, always an error + JMP make_err_ret + +make_save: + PUSH AX ; Save whether Disk or File + MOV AX,CX ; Device ID to AH + CALL NewEntry + POP AX ; 0 if Disk, 3 if File + retnc + MOV AL,2 ; create failed case 2 + return + +make_new: + call make_save + retc ; case 2 fail + TEST BYTE PTR [ATTRIB],attr_directory + retnz ; Don't "open" directories, so don't + ; tell the sharer about them + SaveReg ; Save AL code + invoke ShareEnter + RestoreReg + retnc +; +; We get here by having the user FAIL a share problem. Typically a failure of +; this nature is an out-of-space or an internal error. We clean up as best as +; possible: delete the newly created directory entry and return share_error. +; + PUSH AX + LES DI,CurBuf + MOV BYTE PTR ES:[BX],0E5H ; nuke newly created entry. + + TEST ES:[DI.buf_flags],buf_dirty ;LB. if already dirty ;AN000; + JNZ yesdirty2 ;LB. don't increment dirty count ;AN000; + invoke INC_DIRTY_COUNT ;LB. ;AN000; + OR ES:[DI].buf_flags,buf_dirty ; flag buffer as dirty +yesdirty2: + LES BP,ThisDPB + MOV AL,ES:[BP].DPB_Drive ; get drive for flush + Invoke FlushBuf ; write out buffer. + POP AX + jmp make_Share_ret +; +; We have found an existing file. We have also entered it into the share set. +; At this point we need to call newentry to correctly address the problem of +; getting rid of old data (create an existing file) or creating a new +; directory entry (create a new file). Unfortunately, this operation may +; result in an INT 24 that the user doesn't return from, thus locking the file +; irretrievably into the share set. The correct solution is for us to LEAVE +; the share set now, do the operation and then reassert the share access. +; +; We are allowed to do this! There is no window! After all, we are in +; critDisk here and for someone else to get in, they must enter critDisk also. +; +MakeEndShare: + LES DI,ThisSFT ; grab SFT + XOR AX,AX + EnterCrit critSFT + XCHG AX,ES:[DI].sf_ref_count + SaveReg + PUSHF + invoke ShareEnd ; remove sharing + POPF + RestoreReg + LeaveCrit critSFT + RestoreReg + CALL make_save +; +; If the user failed, we do not reenter into the sharing set. +; + retc ; bye if error + SaveReg + PUSHF + invoke ShareEnter + POPF + RestoreReg +; +; If Share_check fails, then we have an internal ERROR!!!!! +; + return +EndProc MakeNode + +; Inputs: +; [THISSFT] set +; [THISDPB] set +; [LASTENT] current last valid entry number in directory if no free +; entries +; [VOLID] set if a volume ID was found during search +; [ATTRIB] Contains attributes for new file +; [DIRSTART] Points to first cluster of dir (0 means root) +; CARRY FLAG INDICATES STATUS OF SEARCH FOR FILE +; NC means file existed (device) +; C means file did not exist +; AH = Device ID byte +; If FILE +; [CURBUF+2]:BX points to start of directory entry +; [CURBUF+2]:SI points to dir_first of directory entry +; If device +; DS:BX points to start of "fake" directory entry +; DS:SI points to dir_first of "fake" directory entry +; (has DWORD pointer to device header) +; Function: +; Make a new directory entry +; If an old one existed it is truncated first +; Outputs: +; Carry set if error +; Can't grow dir, atts didn't match, attempt to make 2nd +; vol ID, user FAILed to I 24 +; else +; outputs of DOOPEN +; DS, BX, SI preserved (meaning on SI BX, not value), others destroyed + + procedure NEWENTRY,NEAR + DOSAssume CS,,"NewEntry" + ASSUME ES:NOTHING + + LES BP,[THISDPB] +ASSUME ES:NOTHING + JNC EXISTENT + CMP [FAILERR],0 + STC + retnz ; User FAILed, node might exist + CALL BUILDDIR ; Try to build dir + retc ; Failed + invoke GETENT ; Point at that free entry + retc ; Failed + JMP SHORT FREESPOT + +ERRRET3: + STC + return + +EXISTENT: + DOSAssume CS,,"MKNODE/ExistEnt" + OR AH,AH ; Check if file is I/O device + JNS NOT_DEV1 + JMP DOOPEN ; If so, proceed with open + +NOT_DEV1: + invoke FREEENT ; Free cluster chain + retc ; Failed +FREESPOT: + TEST BYTE PTR [ATTRIB],attr_volume_id + JZ NOTVOLID + CMP BYTE PTR [VOLID],0 + JNZ ERRRET3 ; Can't create a second volume ID +NOTVOLID: + MOV ES,WORD PTR [CURBUF+2] + MOV DI,BX + MOV SI,OFFSET DOSGROUP:NAME1 + MOV CX,5 + REP MOVSW + MOVSB ; Move name into dir entry + MOV AL,[ATTRIB] + errnz dir_attr-(dir_name+11) + STOSB ; Attributes +;; File Tagging for Create DOS 4.00 + MOV CL,5 ;FT. assume normal ;AN000; +; CMP [CPSWFLAG],0 ;FT. code page matching on ;AN000; +; JZ NORMFT ;FT. no, make null code page ;AN000; +; invoke Get_Global_CdPg ;FT. get global code page ;AN000; +; STOSW ;FT. tag this file with global code page ;AN000; +; DEC CL ;FT. only 4 ;AN000; +;NORMFT: ;FT. ;AN000; + +;; File Tagging for Create DOS 4.00 + XOR AX,AX + REP STOSW ; Zero pad + invoke DATE16 + XCHG AX,DX + errnz dir_time-(dir_attr+1+2*5) + STOSW ; dir_time + XCHG AX,DX + errnz dir_date-(dir_time+2) + STOSW ; dir_date + XOR AX,AX + PUSH DI ; Correct SI input value (recomputed for new buffer) + + errnz dir_first-(dir_date+2) + STOSW ; Zero dir_first and size + errnz dir_size_l-(dir_first+2) + STOSW + STOSW +updnxt: + errnz <(size dir_entry)-(dir_size_l+4)> + MOV SI,WORD PTR [CURBUF] + + TEST ES:[SI.buf_flags],buf_dirty ;LB. if already dirty ;AN000; + JNZ yesdirty3 ;LB. don't increment dirty count ;AN000; + invoke INC_DIRTY_COUNT ;LB. ;AN000; + OR ES:[SI.buf_flags],buf_dirty +yesdirty3: + LES BP,[THISDPB] + MOV AL,ES:[BP.dpb_drive] ; Sets AH value again (in AL) + PUSH AX + PUSH BX +; If we have a file, we need to increment the open ref. count so that +; we have some protection against invalid media changes if an Int 24 +; error occurs. +; Do nothing for a device. + SaveReg + LES DI,[THISSFT] + test es:[di.sf_flags],devid_device + jnz GotADevice + SaveReg + LDS BX,[THISDPB] + MOV word ptr ES:[DI.sf_devptr],BX + MOV BX,DS + MOV word ptr ES:[DI.sf_devptr+2],BX + RestoreReg ; need to use DS for segment later on + invoke Dev_Open_SFT ; increment ref. count + mov [VIRTUAL_OPEN],1; set flag +GotADevice: + RestoreReg + + PUSH [ACT_PAGE] ;LB. save EMS page for curbuf ;AN000; + invoke FLUSHBUF + POP BX ;LB. restore EMS page for curbuf ;AN000; + PUSHF ;LB. save flushbuf falg ;AN000; + CMP BX,-1 ;BL-NETWORK PTM #-? + JE Page_ok ;BL-NETWORK PTM #-? + invoke SET_MAP_PAGE ;LB. remap curbuf ;AN000; +Page_ok: ;BL-NETWORK PTM #-? + POPF ;LB. restore flush flag ;AN000; + Call CHECK_VIRT_OPEN ; decrement ref. count ;AN000; + POP BX + POP AX + POP SI ; Get SI input back + MOV AH,AL ; Get I/O driver number back + retc ; Failed + + +;NOTE FALL THROUGH + +; Inputs: +; [THISDPB] points to DPB if file +; [THISSFT] points to SFT being used +; AH = Device ID byte +; If FILE +; [CURBUF+2]:BX points to start of directory entry +; [CURBUF+2]:SI points to dir_first of directory entry +; If device +; DS:BX points to start of "fake" directory entry +; DS:SI points to dir_first of "fake" directory entry +; (has DWORD pointer to device header) +; Function: +; Fill in SFT from dir entry +; Outputs: +; CARRY CLEAR +; sf_ref_count and sf_mode fields not altered +; sf_flags high byte = 0 +; sf_flags low byte = AH except +; sf_flags Bit 6 set (not dirty or not EOF) +; sf_attr sf_date sf_time sf_name set from entry +; sf_position = 0 +; If device +; sf_devptr = dword at dir_first (pointer to device header) +; sf_size = 0 +; If file +; sf_firclus sf_size set from entry +; sf_devptr = [THISDPB] +; sf_cluspos = 0 +; sf_lstclus = sf_firclus +; sf_dirsec sf_dirpos set +; DS,SI,BX preserved, others destroyed + + entry DOOPEN + DOSAssume CS,,"DoOpen" + ASSUME ES:NOTHING + +; +; Generate and store attribute +; + MOV DH,AH ; AH to different place + LES DI,[THISSFT] + ADD DI,sf_attr ; Skip ref_count and mode fields + XOR AL,AL ; Assume it's a device, devices have an + ; attribute of 0 (for R/O testing etc). + OR DH,DH ; See if our assumption good. + JS DEV_SFT1 ; If device DS=DOSGROUP + MOV DS,WORD PTR [CURBUF+2] +ASSUME DS:NOTHING + MOV AL,[BX.dir_attr] ; If file, get attrib from dir entry +DEV_SFT1: + STOSB ; sf_attr, ES:DI -> sf_flags +; +; Generate and store flags word +; + XOR AX,AX + MOV AL,DH + OR AL,devid_file_clean + STOSW ; sf_flags, ES:DI -> sf_devptr +; +; Generate and store device pointer +; + PUSH DS + LDS AX,DWORD PTR [BX.dir_first] ; Assume device + OR DH,DH + JS DEV_SFT2 + LDS AX,[THISDPB] ; Was file +DEV_SFT2: + STOSW ; store offset + MOV AX,DS + POP DS + STOSW ; store segment + ; ES:DI -> sf_firclus +; +; Generate pointer to, generate and store first cluster (irrelevant for +; devices) +; + PUSH SI ; Save pointer to dir_first + MOVSW ; dir_first -> sf_firclus + ; DS:SI -> dir_size_l, ES:DI -> sf_time +; +; Copy time/date of last modification +; + SUB SI,dir_size_l - dir_time ; DS:SI->dir_time + MOVSW ; dir_time -> sf_time + ; DS:SI -> dir_date, ES:DI -> sf_date + MOVSW ; dir_date -> sf_date + ; DS:SI -> dir_first, ES:DI -> sf_size +; +; Generate and store file size (0 for devices) +; + LODSW ; skip dir_first, DS:SI -> dir_size_l + LODSW ; dir_size_l in AX , DS:SI -> dir_size_h + MOV CX,AX ; dir_size_l in CX + LODSW ; dir_size_h (size AX:CX), DS:SI -> ???? + OR DH,DH + JNS FILE_SFT1 + XOR AX,AX + MOV CX,AX ; Devices are open ended +FILE_SFT1: + XCHG AX,CX + STOSW ; Low word of sf_size + XCHG AX,CX + STOSW ; High word of sf_size + ; ES:DI -> sf_position +; +; Initialize position to 0 +; + XOR AX,AX + STOSW + STOSW ; sf_position + ; ES:DI -> sf_cluspos +; +; Generate cluster optimizations for files +; + OR DH,DH + JS DEV_SFT3 + STOSW ; sf_cluspos + MOV AX,[BX.dir_first] +;;;; STOSW ; sf_lstclus + PUSH DI ;AN004; save dirsec offset + SUB DI,sf_dirsec ;AN004; es:di -> SFT + MOV ES:[DI.sf_lstclus],AX ;AN004; save it + POP DI ;AN004; restore dirsec offset + + + +; DOS 3.3 FastOpen 6/13/86 + + PUSH DS + context DS + TEST [FastOpenFlg],Special_Fill_Set + JZ Not_FastOpen + MOV SI,OFFSET DOSGROUP:FastOpen_Ext_Info + MOV AX,WORD PTR [SI.FEI_dirsec] + STOSW ; sf_dirsec + MOV AX,WORD PTR [SI.FEI_dirsec+2] ;;; changed for >32mb + STOSW ; sf_dirsec + MOV AL,[SI.FEI_dirpos] + STOSB ; sf_dirpos + POP DS + JMP Next_Name + +; DOS 3.3 FastOpen 6/13/86 + +Not_FastOpen: + POP DS ; normal path +ASSUME DS:NOTHING + MOV SI,WORD PTR [CURBUF] ; DS:SI->buffer header + MOV AX,WORD PTR [SI.buf_sector] ;F.C. >32mb ;AN000; + STOSW ; sf_dirsec ;F.C. >32mb ;AN000; + MOV AX,WORD PTR [SI.buf_sector+2] ;F.C. >32mb ;AN000; + STOSW ; sf_dirsec ;F.C. >32mb ;AN000; + MOV AX,BX + ADD SI,BUFINSIZ ; DS:SI-> start of data in buffer + SUB AX,SI ; AX = BX relative to start of sector + MOV CL,SIZE dir_entry + DIV CL + STOSB ; sf_dirpos + +Next_Name: + errnz sf_name-(sf_dirpos+1) + JMP SHORT FILE_SFT2 + +DEV_SFT3: + ADD DI,sf_name - sf_cluspos +FILE_SFT2: +; +; Copy in the object's name +; + MOV SI,BX ; DS:SI points to dir_name + MOV CX,11 + REP MOVSB ; sf_name + POP SI ; recover DS:SI -> dir_first +;; File tagging , code page and XA cluster must be after name +; MOV AX,[BX.dir_CODEPG] ;FT. set file's code page ;AN000; +; STOSW ;FT. ;AN000; +; MOV AX,[BX.dir_EXTCLUSTER] ;FT. set XA cluster ;AN000; +; STOSW ;FT. ;AN000; +; MOV AX,[EXTOPEN_IO_MODE] ;FT. extended open ;AN000; +; STOSW ;FT. ;AN000; +; MOV AL,[BX.dir_attr2] ;FT. high attribute ;AN000; +; STOSB ;FT. ;AN000; + +;; File tagging , code page and XA cluster must be after name + + context DS + CLC + return + +EndProc NEWENTRY + +; Inputs: +; ES:BP -> DPB +; [CURBUF] Set +; [CURBUF+2]:BX points to directory entry +; [CURBUF+2]:SI points to above dir_first +; Function: +; Free the cluster chain for the entry if present +; Outputs: +; Carry set if error (currently user FAILed to I 24) +; (NOTE dir_firclus and dir_size_l/h are wrong) +; DS BX SI ES BP preserved (BX,SI in meaning, not value) others destroyed + + procedure FREEENT,NEAR + DOSAssume CS,,"FreeEnt" + ASSUME ES:NOTHING + + PUSH DS + LDS DI,[CURBUF] +ASSUME DS:NOTHING + MOV CX,[SI] ; Get pointer to clusters + MOV DX,WORD PTR [DI.buf_sector+2] ;F.C. >32mb ;AN000; + MOV [HIGH_SECTOR],DX ;F.C. >32mb ;AN000; + MOV DX,WORD PTR [DI.buf_sector] + POP DS + DOSAssume CS,,"MKNODE/FreeEnt" + CMP CX,2 + JB RET1 ; Was 0 length file (or mucked Firclus if CX=1) + CMP CX,ES:[BP.dpb_max_cluster] + JA RET1 ; Treat like zero length file (firclus mucked) + SUB BX,DI + PUSH BX ; Save offset + PUSH [HIGH_SECTOR] ;F.C. >32mb ;AN000; + PUSH DX ; Save sector number + + MOV BX,CX + invoke Delete_FSeek ; FS. delete Fastseek Clusters ;AN000; + invoke RELEASE ; Free any data allocated + POP DX + POP [HIGH_SECTOR] ;F.C. >32mb ;AN000; + JNC GET_BUF_BACK + POP BX + return ; Screw up + +GET_BUF_BACK: + + MOV [ALLOWED],allowed_RETRY + allowed_FAIL + XOR AL,AL + invoke GETBUFFR ; Get sector back + POP BX ; Get offset back + retc + invoke SET_BUF_AS_DIR + ADD BX,WORD PTR [CURBUF] ; Correct it for new buffer + MOV SI,BX + ADD SI,dir_first ; Get corrected SI +RET1: + CLC + return +EndProc FREEENT + +; +; CHECK_VIRT_OPEN checks to see if we had performed a "virtual open" (by +; examining the flag [VIRTUAL_OPEN] to see if it is 1). If we did, then +; it calls Dev_Close_SFT to decrement the ref. count. It also resets the +; flag [VIRTUAL_OPEN]. +; No registers affected (including flags). +; On input, [THISSFT] points to current SFT. +; + Procedure CHECK_VIRT_OPEN,NEAR + DOSAssume CS,,"Check_Virt_Open" + + PUSH AX + lahf ; preserve flags + CMP [VIRTUAL_OPEN],0 + JZ ALL_CLOSED + mov [VIRTUAL_OPEN],0 ; reset flag + SaveReg + LES DI,[THISSFT] + INVOKE DEV_CLOSE_SFT + RestoreReg + +ALL_CLOSED: + sahf ; restore flags + POP AX + return + +EndProc CHECK_VIRT_OPEN + + +CODE ENDS + END + \ No newline at end of file diff --git a/v4.0/src/DOS/MSCODE.ASM b/v4.0/src/DOS/MSCODE.ASM new file mode 100644 index 0000000..74668c9 --- /dev/null +++ b/v4.0/src/DOS/MSCODE.ASM @@ -0,0 +1,16 @@ +; SCCSID = @(#)ibmcode.asm 1.1 85/04/10 +TITLE MISC DOS ROUTINES - Int 25 and 26 handlers and other +NAME IBMCODE + +; +; System call dispatch code. +; + +.xlist +.xcref +include mssw.asm +.cref +.list + +include ms_code.asm + END diff --git a/v4.0/src/DOS/MSCONST.ASM b/v4.0/src/DOS/MSCONST.ASM new file mode 100644 index 0000000..126f322 --- /dev/null +++ b/v4.0/src/DOS/MSCONST.ASM @@ -0,0 +1,153 @@ +; SCCSID = @(#)msconst.asm 1.4 85/09/12 +; Revision history +; AN000 version 4.00 Jan. 1988 +; AN007 fake version check for IBMCACHE.COM +include mshead.asm +include version.inc + +CODE SEGMENT BYTE PUBLIC 'CODE' + Extrn LeaveDOS:NEAR + Extrn BadCall:FAR, OKCall:FAR +CODE ENDS + +Break + +; +; We need to identify the parts of the data area that are relevant to tasks +; and those that are relevant to the system as a whole. Under 3.0, the system +; data will be gathered with the system code. The process data under 2.x will +; be available for swapping and under 3.0 it will be allocated per-process. +; +; The data that is system data will be identified by [SYSTEM] in the comments +; describing that data item. +; + + AsmVars + +CONSTANTS SEGMENT WORD PUBLIC 'CONST' + + extrn sfTabl:DWORD + + ORG 0 + + EVEN +; +; WANGO!!! The following word is used by SHARE and REDIR to determin data +; area compatability. This location must be incremented EACH TIME the data +; area here gets mucked with. +; +; Also, do NOT change this position relative to DOSGROUP:0. +; +Public MSCT001S,MSCT001E +MSCT001S: + I_am DataVersion,WORD,<1> ;AC000; [SYSTEM] version number for DOS DATA + +%out WARNING!!! Debug fields are being included!!! + DB "BUG " ; THIS FIELD MUST BE EVEN # OF BYTES + I_am BugTyp,WORD,<0> + I_am BugLev,WORD,<0> +include bugtyp.asm + + I_am MYNUM,WORD,<0> ; [SYSTEM] A number that goes with MYNAME + I_am FCBLRU,WORD,<0> ; [SYSTEM] LRU count for FCB cache + I_am OpenLRU,WORD,<0> ; [SYSTEM] LRU count for FCB cache opens +; NOTE: We include the decl of OEM_HANDLER in IBM DOS even though it is not used. +; This allows the REDIRector to work on either IBM or MS-DOS. + PUBLIC OEM_HANDLER +OEM_HANDLER DD -1 ; [SYSTEM] Pointer to OEM handler code + I_am LeaveAddr,WORD,<> ; [SYSTEM] + I_am RetryCount,WORD,<3> ; [SYSTEM] Share retries + I_am RetryLoop,WORD,<1> ; [SYSTEM] Share retries + I_am LastBuffer,DWORD,<-1,-1>; [SYSTEM] Buffer queue recency pointer + I_am CONTPOS,WORD ; [SYSTEM] location in buffer of next read + I_am arena_head,WORD ; [SYSTEM] Segment # of first arena in memory +; The following block of data is used by SYSINIT. Do not change the order or +; size of this block + PUBLIC SYSINITVAR ; [SYSTEM] +SYSINITVAR LABEL WORD ; [SYSTEM] + I_am DPBHEAD,DWORD ; [SYSTEM] Pointer to head of DPB-FAT list + I_am sft_addr,DWORD,<,?> ; [SYSTEM] Pointer to first SFT table + I_am BCLOCK,DWORD ; [SYSTEM] The CLOCK device + I_am BCON,DWORD ; [SYSTEM] Console device entry points + I_am MAXSEC,WORD,<128> ; [SYSTEM] Maximum allowed sector size + I_am BUFFHEAD,DWORD ; [SYSTEM] Pointer to head of buffer queue + I_am CDSADDR,DWORD ; [SYSTEM] Pointer to curdir structure table + I_am sftFCB,DWORD ; [SYSTEM] pointer to FCB cache table + I_am KeepCount,WORD ; [SYSTEM] count of FCB opens to keep + I_am NUMIO,BYTE ; [SYSTEM] Number of disk tables + I_am CDSCOUNT,BYTE ; [SYSTEM] Number of CDS structures in above +; A fake header for the NUL device + I_am NULDEV,DWORD ; [SYSTEM] Link to rest of device list + DW DEVTYP OR ISNULL ; [SYSTEM] Null device attributes + short_addr SNULDEV ; [SYSTEM] Strategy entry point + short_addr INULDEV ; [SYSTEM] Interrupt entry point + DB "NUL " ; [SYSTEM] Name of null device + I_am Splices,BYTE,<0> ; [SYSTEM] TRUE => splices being done + I_am Special_Entries,WORD,<0>; [SYSTEM] address of specail entries ;AN000; + I_am IFS_DOS_CALL,DWORD ; [SYSTEM] entry for IFS DOS service ;AN000; + I_am IFS_HEADER,DWORD ; [SYSTEM] IFS header chain ;AN000; + I_am BUFFERS_PARM1,WORD,<0> ; [SYSTEM] value of BUFFERS= ,m ;AN000; + I_am BUFFERS_PARM2,WORD,<0> ; [SYSTEM] value of BUFFERS= ,n ;AN000; + I_am BOOTDRIVE,BYTE ; [SYSTEM] the boot drive ;AN000; + I_am DDMOVE,BYTE,<0> ; [SYSTEM] 1 if we need DWORD move ;AN000; + I_am EXT_MEM_SIZE,WORD,<0> ; [SYSTEM] extended memory size ;AN000; + + PUBLIC HASHINITVAR ; [SYSTEM] ;AN000; +HASHINITVAR LABEL WORD ; [SYSTEM] ;AN000; + I_am BUF_HASH_PTR,DWORD ; [SYSTEM] buffer Hash table addr ;AN000; + I_am BUF_HASH_COUNT,WORD,<1> ; [SYSTEM] number of Hash entries ;AN000; + I_am SC_CACHE_PTR,DWORD ; [SYSTEM] secondary cache pointer ;AN000; + I_am SC_CACHE_COUNT,WORD,<0> ; [SYSTEM] secondary cache count ;AN000; + +IF BUFFERFLAG + + I_am BUF_EMS_SAFE_FLAG,BYTE,<1> ; indicates whether the page used by buffers is safe or not + I_am BUF_EMS_LAST_PAGE,4,<0,0,0,0> ; holds the last page above 640k + I_am BUF_EMS_FIRST_PAGE,4,<0,0,0,0> ; holds the first page above 640K + I_am BUF_EMS_NPA640,WORD,<0> ; holds the number of pages above 640K + +ENDIF + + I_am BUF_EMS_MODE,BYTE,<-1> ; [SYSTEM] EMS mode ;AN000; + I_am BUF_EMS_HANDLE,WORD ; [SYSTEM] buffer EMS handle ;AN000; + I_am BUF_EMS_PAGE_FRAME,WORD ,<-1>;[SYSTEM] EMS page frame number ;AN000; + I_am BUF_EMS_SEG_CNT,WORD,<1>; [SYSTEM] EMS seg count ;AN000; + I_am BUF_EMS_PFRAME,WORD ; [SYSTEM] EMS page frame seg address ;AN000; + I_am BUF_EMS_RESERV,WORD,<0> ; [SYSTEM] reserved ;AN000; + +IF BUFFERFLAG + I_am BUF_EMS_MAP_BUFF,1,<0> ; this is not used to save the state of the + ; of the buffers page. this one byte is + ; retained to keep the size of this data + ; block the same. +ELSE + I_am BUF_EMS_MAP_BUFF,12,<0,0,0,0,0,0,0,0,0,0,0,0> ; map buufer ;AN000; +ENDIF + +; End of SYSINITVar block + +; +; Sharer jump table +; +PUBLIC JShare + EVEN +JShare LABEL DWORD + DW OFFSET DOSGROUP:BadCall, 0 + DW OFFSET DOSGROUP:OKCall, 0 ; 1 MFT_enter + DW OFFSET DOSGROUP:OKCall, 0 ; 2 MFTClose + DW OFFSET DOSGROUP:BadCall, 0 ; 3 MFTclU + DW OFFSET DOSGROUP:BadCall, 0 ; 4 MFTCloseP + DW OFFSET DOSGROUP:BadCall, 0 ; 5 MFTCloN + DW OFFSET DOSGROUP:BadCall, 0 ; 6 set_block + DW OFFSET DOSGROUP:BadCall, 0 ; 7 clr_block + DW OFFSET DOSGROUP:OKCall, 0 ; 8 chk_block + DW OFFSET DOSGROUP:BadCall, 0 ; 9 MFT_get + DW OFFSET DOSGROUP:BadCall, 0 ; 10 ShSave + DW OFFSET DOSGROUP:BadCall, 0 ; 11 ShChk + DW OFFSET DOSGROUP:OKCall , 0 ; 12 ShCol + DW OFFSET DOSGROUP:BadCall, 0 ; 13 ShCloseFile + DW OFFSET DOSGROUP:BadCall, 0 ; 14 ShSU + +MSCT001E: +CONSTANTS ENDS + \ No newline at end of file diff --git a/v4.0/src/DOS/MSCPMIO.ASM b/v4.0/src/DOS/MSCPMIO.ASM new file mode 100644 index 0000000..53656ff --- /dev/null +++ b/v4.0/src/DOS/MSCPMIO.ASM @@ -0,0 +1,17 @@ +; SCCSID = @(#)ibmcpmio.asm 1.1 85/04/10 +; +; Standard device IO for MSDOS (first 12 function calls) +; + +.xlist +.xcref +include mssw.asm +include dosseg.asm +.cref +.list + +TITLE IBMCPMIO - device IO for MSDOS +NAME IBMCPMIO + +include cpmio.asm + \ No newline at end of file diff --git a/v4.0/src/DOS/MSCTRLC.ASM b/v4.0/src/DOS/MSCTRLC.ASM new file mode 100644 index 0000000..8343b08 --- /dev/null +++ b/v4.0/src/DOS/MSCTRLC.ASM @@ -0,0 +1,16 @@ +; SCCSID = @(#)ibmctrlc.asm 1.1 85/04/10 +; +; ^C and error handler for MSDOS +; + +.xlist +.xcref +include mssw.asm +.cref +.list + +TITLE Control C detection, Hard error and EXIT routines +NAME IBMCTRLC + +include ctrlc.asm + \ No newline at end of file diff --git a/v4.0/src/DOS/MSDISP.ASM b/v4.0/src/DOS/MSDISP.ASM new file mode 100644 index 0000000..a0f069e --- /dev/null +++ b/v4.0/src/DOS/MSDISP.ASM @@ -0,0 +1,17 @@ +; SCCSID = @(#)ibmdisp.asm 1.1 85/04/10 +TITLE IBM DOS DISPATCHER - System call dispatch code +NAME DISP + +; +; System call dispatch code +; + +.xlist +.xcref +include mssw.asm +.cref +.list + +include disp.asm + END + \ No newline at end of file diff --git a/v4.0/src/DOS/MSDOS.LNK b/v4.0/src/DOS/MSDOS.LNK new file mode 100644 index 0000000..2d43bdb --- /dev/null +++ b/v4.0/src/DOS/MSDOS.LNK @@ -0,0 +1,59 @@ +..\inc\nibdos.obj + +..\inc\const2.obj + +..\inc\msdata.obj + +..\inc\mstable.obj + + msdisp.obj + + mscode.obj + +..\inc\msdosme.obj + + time.obj + + getset.obj + + parse.obj + + misc.obj + + misc2.obj + + crit.obj + + cpmio.obj + + cpmio2.obj + + fcbio.obj + + fcbio2.obj + + search.obj + + path.obj + + ioctl.obj + + delete.obj + + rename.obj + + finfo.obj + + dup.obj + + create.obj + + open.obj + + dinfo.obj + + isearch.obj + + abort.obj + + close.obj + + dircall.obj + + disk.obj + + disk2.obj + + disk3.obj + + dir.obj + + dir2.obj + + dev.obj + + mknode.obj + + rom.obj + + fcb.obj + + msctrlc.obj + + fat.obj + + buf.obj + + proc.obj + + alloc.obj + + srvcall.obj + + util.obj + + handle.obj + + macro.obj + + macro2.obj + + file.obj + + lock.obj + + share.obj + + extattr.obj + + ifs.obj +MSDOS.EXE +MSDOS.MAP /M +; + diff --git a/v4.0/src/DOS/MSDOS.SKL b/v4.0/src/DOS/MSDOS.SKL new file mode 100644 index 0000000..c76c224 --- /dev/null +++ b/v4.0/src/DOS/MSDOS.SKL @@ -0,0 +1,17 @@ + +:class 1 +; This was taken from DEVMES.INC IN G:USA\ ... +; DIVMES DB 13,10,"Divide overflow",13,10 + +:use 001 msdos DIVMES + +:class 3 + +;This is for Yes No check +:use 205 command NLS_YES +:use 206 command NLS_NO +:use 002 msdos NLS_yes2 +:use 003 msdos NLS_no2 + +:end + \ No newline at end of file diff --git a/v4.0/src/DOS/MSHALO.ASM b/v4.0/src/DOS/MSHALO.ASM new file mode 100644 index 0000000..dc6c64a --- /dev/null +++ b/v4.0/src/DOS/MSHALO.ASM @@ -0,0 +1,247 @@ +; SCCSID = @(#)ibmhalo.asm 1.1 85/04/10 +; On 2K (800h) boundaries beginning at address C0000h and ending at EF800h +; there is a header that describes a block of rom program. This header +; contains information needed to initialize a module and to provide PCDOS +; with a set of reserved names for execution. +; +; This header has the following format: +; +; rom_header STRUC +; Signature1 DB 55h +; Signature2 DB AAh +; rom_length DB ? ; number of 512 byte pieces +; init_jmp DB 3 dup (?) +; name_list name_struc <> +; rom_header ENDS +; +; name_struc STRUC +; name_len DB ? +; name_text DB ? DUP (?) +; name_jmp DB 3 DUP (?) +; name_struc ENDS +; +; The name list is a list of names that are reserved by a particular section +; of a module. This list of names is terminated by a null name (length +; is zero). +; +; Consider now, the PCDOS action when a user enters a command: +; +; COMMAND.COM has control. +; o If location FFFFEh has FDh then +; o Start scanning at C0000h, every 800h for a byte 55h followed +; by AAh, stop scan if we get above or = F0000H +; o When we've found one, compare the name entered by the user +; with the one found in the rom. If we have a match, then +; set up the environment for execution and do a long jump +; to the near jump after the found name. +; o If no more names in the list, then continue scanning the module +; for more 55h followed by AAh. +; o We get to this point only if there is no matching name in the +; rom. We now look on disk for the command. +; +; This gives us the flexibility to execute any rom cartridge without having +; to 'hard-code' the name of the cartridge into PCDOS. Rom modules that +; want to be invisible to the DOS should not have any names in their lists +; (i.e. they have a single null name). +; +; Consider a new release of BASIC, say, that patches bugs in the ROM version. +; Clearly this version will be available on disk. How does a user actually +; invoke this new BASIC?? He cannot call it BASIC on the disk because the +; EXEC loader will execute the ROM before it even looks at the disk! Only +; solution: +; +; o Keep things consistent and force the user to have his software named +; differently from the ROM names (BASIC1, BASIC2, etc). + +rom_header STRUC + Signature1 DB ? + Signature2 DB ? + rom_length DB ? + init_jmp DB 3 dup (?) + name_list DB ? +rom_header ENDS + +name_struc STRUC + name_len DB ? + name_text DB 1 DUP (?) + name_jmp DB 3 DUP (?) +name_struc ENDS + +ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + +; +; Check for IBM HALO rom cartrides. DS:DX is a pointer to name +; +ROM_SCAN: + PUSH ES + PUSH SI + PUSH DI + PUSH CX + PUSH AX + PUSH BX +; +; check for halo signature in rom +; + MOV AX,0F000h + MOV ES,AX + CMP BYTE PTR ES:[0FFFEh],0FDh + JZ SCAN_IT +NO_ROM: + CLC +ROM_RET: + POP BX + POP AX + POP CX + POP DI + POP SI + POP ES + RET +SCAN_IT: +; +; start scanning at C000 +; + MOV AX,0C000h +SCAN_ONE: + MOV ES,AX + XOR DI,DI +SCAN_MODULE: +; +; check for a valid header +; + CMP WORD PTR ES:[DI],0AA55h + JZ SCAN_LIST + ADD AX,080h +SCAN_END: + CMP AX,0F000h + JB SCAN_ONE + JMP NO_ROM +; +; trundle down list of names +; +SCAN_LIST: + MOV BL,ES:[DI].rom_length ; number of 512-byte jobbers + XOR BH,BH ; nothing in the high byte + SHL BX,1 + SHL BX,1 ; number of paragraphs + ADD BX,7Fh + AND BX,0FF80h ; round to 2k + + MOV DI,name_list +SCAN_NAME: + MOV CL,ES:[DI] ; length of name + INC DI ; point to name + XOR CH,CH + OR CX,CX ; zero length name + JNZ SCAN_TEST ; nope... compare + ADD AX,BX ; yep, skip to next block + JMP SCAN_END +; +; compare a single name +; +SCAN_TEST: + MOV SI,DX + INC SI + REPE CMPSB ; compare name + JZ SCAN_FOUND ; success! +SCAN_NEXT: + ADD DI,CX ; failure, next name piece + ADD DI,3 + JMP SCAN_NAME +; +; found a name. save entry location +; +SCAN_FOUND: + CMP BYTE PTR DS:[SI],'?' + JZ SCAN_SAVE + CMP BYTE PTR DS:[SI],' ' + JNZ SCAN_NEXT +SCAN_SAVE: + MOV [rom_cs],ES + MOV [ROM_ip],DI + STC + JMP ROM_RET + +; +; execute a rom-placed body of code. allocate largest block +; +ROM_EXEC: + MOV BX,0FFFFh + MOV AH,ALLOC + INT int_command + MOV AH,ALLOC + INT int_command + PUSH BX + PUSH AX +; +; set terminate addresses +; + MOV AX,(set_interrupt_vector SHL 8) + int_terminate + PUSH DS + MOV DS,[RESSEG] + ASSUME DS:RESGROUP + MOV DX,OFFSET RESGROUP:EXEC_WAIT + INT int_command + MOV DX,DS + MOV ES,DX + ASSUME ES:RESGROUP + POP DS + ASSUME DS:NOTHING +; +; and create program header and dup all jfn's +; + POP DX + MOV AH,DUP_PDB + INT int_command +; +; set up dma address +; + MOV DS,DX + MOV DX,080h + MOV AH,SET_DMA + INT int_command +; +; copy in environment info +; + MOV AX,[ENVIRSEG] + MOV DS:[PDB_environ],AX +; +; set up correct size of block +; + POP BX ; BX has size, DS has segment + MOV DX,DS + ADD DX,BX + MOV DS:[PDB_block_len],DX +; +; change ownership of block +; + MOV DX,DS + DEC DX + MOV DS,DX + INC DX + MOV DS:[arena_owner],DX + MOV DS,DX +; +; set up correct stack +; + CMP BX,1000h + JB GOT_STACK + XOR BX,BX +GOT_STACK: + MOV CL,4 + SHL BX,CL + MOV DX,DS + MOV SS,DX + MOV SP,BX + XOR AX,AX + PUSH AX +; +; set up initial registers and go to the guy +; + NOT AX + PUSH [ROM_CS] + PUSH [ROM_IP] + MOV ES,DX +ASSUME ES:NOTHING +FOOBAR PROC FAR + RET +FOOBAR ENDP diff --git a/v4.0/src/DOS/MSINIT.ASM b/v4.0/src/DOS/MSINIT.ASM new file mode 100644 index 0000000..cbd9eaf --- /dev/null +++ b/v4.0/src/DOS/MSINIT.ASM @@ -0,0 +1,667 @@ +; SCCSID = @(#)msinit.asm 1.2 85/07/23 +; TITLE MSINIT.ASM -- MS-DOS INITIALIZATION CODE +; AN000 version 4.0 Jan. 1988 +; AN007 PTM 3957 - fake version for IBMCACHE.COM +; AN008 PTM 4070 - fake version for MS WINDOWS +include sysvar.inc +include doscntry.inc +include fastopen.inc + + I_need DMAAdd,DWORD ; current dma address + I_need DPBHead,DWORD ; long pointer to DPB chain + I_need SFT_Addr,DWORD ; pointer to open file list + I_need NumIO,BYTE ; number of physical drives + I_need BuffHead,DWORD ; pointer to buffer chain + I_need EndMem,WORD ; first unavailable address in memory + I_need CurrentPDB,WORD ; current process ID + I_need CreatePDB,BYTE ; TRUE => create a new PDB + I_need Arena_Head,WORD ; paragraph address of head of arena + I_need sfTabl,BYTE ; internal file table + I_need SysInitVar,BYTE ; label for internal structures + I_need NulDev,DWORD ; long pointer to device chain + I_need BCon,DWORD ; pointer to console device + I_need BClock,DWORD ; pointer to clock device + I_need CallUnit,BYTE ; unit field in dd packet + I_need CallBPB,DWORD ; returned BPB from DD + I_need Maxsec,WORD + I_need Dskchret,BYTE + I_need Devcall,BYTE + i_need Header,BYTE + I_need JShare,DWORD + I_need COUNTRY_CDPG,BYTE ; country info table, DOS 3.3 + I_need SysInitTable,BYTE ; sys init table for SYSINIT + I_need FastOpenTable,BYTE ; table for FASTOPEN + I_need FETCHI_TAG,WORD ; TAG CHECK + I_need Special_Entries,WORD ; address of special entries ;AN007; + I_need IFS_DOS_CALL,DWORD ; IFS IBMDOS CALL entry ;AN000; + I_need HASHINITVAR,WORD ; hash table variables ;AN000; + I_need Packet_Temp,WORD ; used for initial Hash table;AN000; + I_need BUF_HASH_PTR,DWORD ; used for initial Hash table;AN000; + I_need SWAP_ALWAYS_AREA,DWORD ; swap always area addr ;AN000; + I_need SWAP_ALWAYS_AREA_LEN,WORD; swap always area length ;AN000; + I_need SWAP_IN_DOS,DWORD ; swap in dos area ;AN000; + I_need SWAP_IN_DOS_LEN,WORD ; swap in dos area length ;AN000; + I_need SWAP_AREA_LEN,WORD ; swap area length ;AN000; + I_need SWAP_START,BYTE ; swap start addr ;AN000; + I_need SWAP_ALWAYS,BYTE ; swap always addr ;AN000; + I_need Hash_Temp,WORD ; temporary Hash table ;AN000; + +CODE SEGMENT BYTE PUBLIC 'CODE' + Extrn IRETT:NEAR,INT2F:NEAR,CALL_ENTRY:NEAR,QUIT:NEAR,IFS_DOSCALL:FAR + Extrn COMMAND:NEAR,ABSDRD:NEAR,ABSDWRT:NEAR +CODE ENDS + +DATA SEGMENT WORD PUBLIC 'DATA' + ORG 0 ; reset to beginning of data segment + +Public MSINI001S,MSINI001E +MSINI001S label byte +INITBLOCK DB 110H DUP(0) ; Allow for segment round up + +INITSP DW ? +INITSS DW ? +MSINI001E label byte + +ASSUME CS:DOSGROUP,SS:NOTHING + +MOVDPB: + DOSAssume CS,,"MovDPB" +; This section of code is safe from being overwritten by block move + MOV SS,CS:[INITSS] + MOV SP,CS:[INITSP] + REP MOVS BYTE PTR [DI],[SI] + CLD + MOV WORD PTR ES:[DMAADD+2],DX + MOV SI,WORD PTR [DPBHEAD] ; Address of first DPB + MOV WORD PTR ES:[DPBHEAD+2],ES + MOV WORD PTR ES:[sft_addr+2],ES + MOV CL,[NUMIO] ; Number of DPBs + XOR CH,CH +SETFINDPB: + MOV WORD PTR ES:[SI.dpb_next_dpb+2],ES + MOV ES:[SI.dpb_first_access],-1 ; Never accessed before + ADD SI,DPBSIZ ; Point to next DPB + LOOP SETFINDPB + SUB SI,DPBSIZ + MOV WORD PTR ES:[SI.dpb_next_dpb+2],-1 + +;; PUSH ES +;; MOV DI,OFFSET DOSGroup:SYSBUF + 0Fh +;; RCR DI,1 +;; SHR DI,1 +;; SHR DI,1 +;; SHR DI,1 +;; MOV AX,ES +;; ADD AX,DI +;; MOV ES,AX +;; ASSUME ES:NOTHING +;; XOR DI,DI + +; MOV DI,OFFSET DOSGroup:SYSBUF ; Set up one default buffer +; MOV WORD PTR [BUFFHEAD+2],ES +; MOV WORD PTR [BUFFHEAD],DI +;; MOV WORD PTR [Hash_Temp+4],ES ;LB. intitialize one Hash entry ;AN000; +;; MOV WORD PTR [Hash_Temp+2],DI ;LB. ;AN000; +;; MOV WORD PTR [Hash_Temp+6],0 ;LB. dirty count =0 ;AN000; +;; MOV WORD PTR ES:[DI.buf_ID],00FFH +;; MOV WORD PTR ES:[DI.buf_next],DI ;;;1/19/88 +;; MOV WORD PTR ES:[DI.buf_prev],DI ;;;1/19/88 + +;; POP ES + MOV SI,OFFSET DOSGROUP:Version_Fake_Table ;MS.;AN007;move special + MOV DI,ES:[Special_Entries] ;MS.;AN007;entries + MOV CX,ES:[Temp_Var] ;MS.;AN007; + REP MOVSB ;MS.;AN007; + + ASSUME ES:DOSGroup + + PUSH ES + INC DX ; Leave enough room for the ARENA + MOV SI,EndMem + invoke $Dup_PDB +; MOV BYTE PTR [CreatePDB],0FFh ; create jfns and set CurrentPDB +; invoke $CREATE_PROCESS_DATA_BLOCK ; Set up segment +ASSUME DS:NOTHING,ES:NOTHING + POP ES + DOSAssume CS,,"INIT/CreateProcess" +; +; set up memory arena +;SPECIAL NOTE FOR HIGHMEM VERSION +; At this point a process header has been built where the start of the CONSTANTS +; segment as refed by CS is. From this point until the return below be careful +; about references off of CS. +; + MOV AX,[CurrentPDB] + MOV ES:[CurrentPDB],AX ; Put it in the REAL location + MOV BYTE PTR ES:[CreatePDB],0h ; reset flag in REAL location + DEC AX + MOV ES:[arena_head],AX + PUSH DS + MOV DS,AX + MOV DS:[arena_signature],arena_signature_end + MOV DS:[arena_owner],arena_owner_system + SUB AX,ES:[ENDMEM] + NEG AX + DEC AX + MOV DS:[arena_size],AX + POP DS + + MOV DI,OFFSET DOSGROUP:sftabl + SFTable ; Point to sft 0 + MOV AX,3 + STOSW ; Adjust Refcount + MOV DI,OFFSET DOSGROUP:SySInitTable + + IF NOT Installed + invoke NETWINIT +; ELSE +; invoke NETWINIT +; %OUT Random NETWINIT done at install + ENDIF + +procedure XXX,FAR + RET +EndProc XXX +DATA ENDS + +; the next segment defines a new class that MUST appear last in the link map. +; This defines several important locations for the initialization process that +; must be the first available locations of free memory. + +LAST SEGMENT PARA PUBLIC 'LAST' + PUBLIC SYSBUF + PUBLIC MEMSTRT + +SYSBUF LABEL WORD +ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + +INITIRET: ; Temp IRET instruction + IRET + + entry DOSINIT + CLI + CLD + MOV [ENDMEM],DX + MOV [INITSP],SP + MOV [INITSS],SS + MOV AX,CS + MOV SS,AX +ASSUME SS:DOSGROUP + MOV SP,OFFSET DOSGROUP:INITSTACK + MOV WORD PTR [NULDEV+2],DS + MOV WORD PTR [NULDEV],SI ; DS:SI Points to CONSOLE Device + + PUSH DS ; Need Crit vector inited to use DEVIOCALL + XOR AX,AX + MOV DS,AX + MOV AX,OFFSET DOSGROUP:INITIRET + MOV DS:[addr_int_IBM],AX + MOV AX,CS + MOV DS:[addr_int_IBM+2],AX + POP DS + + CALL CHARINIT + PUSH SI ; Save pointer to header + PUSH CS + POP ES + ASSUME ES:DOSGROUP + MOV DI,OFFSET DOSGROUP:sftabl + SFTable ; Point to sft 0 + MOV AX,3 + STOSW ; Refcount + DEC AL + errnz sf_mode-(sf_ref_count+2) + STOSW ; Access rd/wr, compatibility + XOR AL,AL + errnz sf_attr-(sf_mode+2) + STOSB ; attribute + MOV AL,devid_device_EOF OR devid_device OR ISCIN OR ISCOUT + errnz sf_flags-(sf_attr+1) + STOSW ; Flags + MOV AX,SI + errnz sf_devptr-(sf_flags+2) + STOSW ; Device pointer in devptr + MOV AX,DS + STOSW + XOR AX,AX + errnz sf_firclus-(sf_devptr+4) + STOSW ; firclus + errnz sf_time-(sf_firclus+2) + STOSW ; time + errnz sf_date-(sf_time+2) + STOSW ; date + DEC AX + errnz sf_size-(sf_date+2) + STOSW ; size + STOSW + INC AX + errnz sf_position-(sf_size+4) + STOSW ; position + STOSW + ADD DI,sf_name - sf_cluspos ;Point at name + ADD SI,SDEVNAME ; Point to name + MOV CX,4 + REP MOVSW ; Name + MOV CL,3 + MOV AL," " + REP STOSB ; Extension + POP SI ; Get back pointer to header + OR BYTE PTR [SI.SDEVATT],ISCIN OR ISCOUT + MOV WORD PTR [BCON],SI + MOV WORD PTR [BCON+2],DS +CHAR_INIT_LOOP: + LDS SI,DWORD PTR [SI] ; AUX device + CALL CHARINIT + TEST BYTE PTR [SI.SDEVATT],ISCLOCK + JZ CHAR_INIT_LOOP + MOV WORD PTR [BCLOCK],SI + MOV WORD PTR [BCLOCK+2],DS + MOV BP,OFFSET DOSGROUP:MEMSTRT ; ES:BP points to DPB +PERDRV: + LDS SI,DWORD PTR [SI] ; Next device + CMP SI,-1 + JZ CONTINIT + CALL CHARINIT + TEST [SI.SDEVATT],DEVTYP + JNZ PERDRV ; Skip any other character devs + MOV CL,[CALLUNIT] + XOR CH,CH + MOV [SI.SDEVNAME],CL ; Number of units in name field + MOV DL,[NUMIO] + XOR DH,DH + ADD [NUMIO],CL + PUSH DS + PUSH SI + LDS BX,[CALLBPB] +PERUNIT: + MOV SI,[BX] ; DS:SI Points to BPB + INC BX + INC BX ; On to next BPB + MOV ES:[BP.dpb_drive],DL + MOV ES:[BP.dpb_UNIT],DH + PUSH BX + PUSH CX + PUSH DX + invoke $SETDPB + MOV AX,ES:[BP.dpb_sector_size] + CMP AX,[MAXSEC] + JBE NOTMAX + MOV [MAXSEC],AX +NOTMAX: + + POP DX + POP CX + POP BX + MOV AX,DS ; Save DS + POP SI + POP DS + MOV WORD PTR ES:[BP.dpb_driver_addr],SI + MOV WORD PTR ES:[BP.dpb_driver_addr+2],DS + PUSH DS + PUSH SI + INC DH + INC DL + MOV DS,AX + ADD BP,DPBSIZ + LOOP PERUNIT + POP SI + POP DS + JMP PERDRV + +CONTINIT: + PUSH CS + POP DS +ASSUME DS:DOSGROUP +; +; BP has the current offset to the allocated DPBs. Calculate true address of +; buffers, FATs, free space +; + MOV DI,BP ; First byte after current DPBs +; +; Compute location of first buffer. If we are to make buffers paragraph +; aligned, change this code to make sure that AX = 0 mod 16 and change the +; setting of the segment address part of BuffHead to make sure that the offset +; is zero. Alternatively, this may be done by making segment LAST paragraph +; aligned. +; +;;; MOV BP,[MAXSEC] ; get size of buffer + MOV AX,OFFSET DOSGROUP:SYSBUF +; +; Compute location of DPBs +; +;;; ADD AX,BP ; One I/O buffer +;;; ADD AX,BUFINSIZ + MOV WORD PTR [DPBHEAD],AX ; True start of DPBs + MOV DX,AX + SUB DX,OFFSET DOSGROUP:SYSBUF + MOV BP,DX + ADD BP,DI ; Allocate buffer space + SUB BP,ADJFAC ; True address of free memory + PUSH BP + MOV DI,OFFSET DOSGROUP:MEMSTRT ; Current start of DPBs + ADD DI,dpb_next_dpb ; Point at dpb_next_dpb field + MOV CL,[NUMIO] + XOR CH,CH +TRUEDPBAD: + ADD AX,DPBSIZ ; Compute address of next DPB + STOSW ; Set the link to next DPB + ADD DI,DPBSIZ-2 ; Point at next address + LOOP TRUEDPBAD + SUB DI,DPBSIZ ; Point at last dpb_next_dpb field + MOV AX,-1 + STOSW ; End of list + + MOV [Special_Entries],BP ;MS.;AN007 save starting address of Special entries + MOV SI,OFFSET DOSGROUP:Version_Fake_Table ;MS.;AN007 + MOV DX,SI ;MS.;AN007 + XOR AH,AH ;MS.;AN007 +NextEntry: ;MS.;AN007 + LODSB ;MS.;AN007 get name length + OR AL,AL ;MS.;AN007 end of list + JZ endlist ;MS.;AN007 yes + ADD SI,AX ;MS.;AN007 position to + ADD SI,3 ;MS.;AN007 next entry + JMP NextEntry ;MS.;AN007 +endlist: ;MS.;AN007 + SUB SI,DX ;MS.;AN007 + MOV [Temp_Var],SI ;MS.;AN007 si = total table length + ADD BP,SI ;MS.;AN007 + + + ADD BP,15 ; True start of free space (round up to segment) + RCR BP,1 + MOV CL,3 + SHR BP,CL ; Number of segments for DOS resources +;;;;;; MOV [IBMDOS_SIZE],BP ;MS. save it for information + MOV DX,CS + ADD DX,BP ; First free segment + MOV BX,0FH + MOV CX,[ENDMEM] + + IF HIGHMEM + SUB CX,BP + MOV BP,CX ; Segment of DOS + MOV DX,CS ; Program segment + ENDIF + + IF NOT HIGHMEM + MOV BP,CS + ENDIF + +; BP has segment of DOS (whether to load high or run in place) +; DX has program segment (whether after DOS or overlaying DOS) +; CX has size of memory in paragraphs (reduced by DOS size if HIGHMEM) + MOV [ENDMEM],CX + MOV ES,BP +ASSUME ES:DOSGROUP + + IF HIGHMEM + XOR SI,SI + MOV DI,SI + MOV CX,OFFSET DOSGROUP:SYSBUF ;# bytes to move + SHR CX,1 ;# words to move (carry set if odd) + REP MOVSW ; Move DOS to high memory + JNC NOTODD + MOVSB +NOTODD: + ENDIF + + MOV WORD PTR ES:[DSKCHRET+3],ES + XOR AX,AX + MOV DS,AX + MOV ES,AX +ASSUME DS:NOTHING,ES:NOTHING + MOV DI,INTBASE+2 + MOV AX,BP ; Final DOS segment to AX + + EXTRN DIVOV:near + MOV WORD PTR DS:[0],OFFSET DOSGROUP:DIVOV ; Set default divide trap address + MOV DS:[2],AX + +; Set vectors 20-28 and 2A-3F to point to IRET. + + MOV CX,17 + REP STOSW ; Set 9 segments + ; Sets segs for INTs 20H-28H + ADD DI,6 ; Skip INT 29H vector (FAST CON) as it may + ; already be set. + MOV CX,43 + REP STOSW ; Set 22 segments + ; Sets segs for vectors 2AH-3FH + + MOV DI,INTBASE + MOV AX,OFFSET DOSGROUP:IRETT + MOV CX,9 ; Set 9 offsets (skip 2 between each) + ; Sets offsets for INTs 20H-28H + +ISET1: + STOSW + ADD DI,2 + LOOP ISET1 + + ADD DI,4 ; Skip vector 29H + + MOV CX,22 ; Set 22 offsets (skip 2 between each) + ; Sets offsets for INTs 2AH-3FH + +ISET2: + STOSW + ADD DI,2 + LOOP ISET2 + + MOV AX,BP ; Final DOS segment to AX + +IF installed +; the following two are in the Code segment, thus the CS +; overrides + MOV WORD PTR DS:[02FH * 4],OFFSET DOSGROUP:INT2F +ENDIF + +; Set up entry point call at vectors 30-31H + MOV BYTE PTR DS:[ENTRYPOINT],mi_Long_JMP + MOV WORD PTR DS:[ENTRYPOINT+1],OFFSET DOSGROUP:CALL_ENTRY + MOV WORD PTR DS:[ENTRYPOINT+3],AX + + IF ALTVECT + MOV DI,ALTBASE+2 + MOV CX,15 + REP STOSW ; Set 8 segments (skip 2 between each) + ENDIF + + MOV WORD PTR DS:[addr_int_abort],OFFSET DOSGROUP:QUIT + MOV WORD PTR DS:[addr_int_command],OFFSET DOSGROUP:COMMAND + MOV WORD PTR DS:[addr_int_terminate],100H + MOV WORD PTR DS:[addr_int_terminate+2],DX + MOV WORD PTR DS:[addr_int_disk_read],OFFSET DOSGROUP:ABSDRD ; INT 25 + MOV WORD PTR DS:[addr_int_disk_write],OFFSET DOSGROUP:ABSDWRT ; INT 26 + EXTRN Stay_resident:NEAR + MOV WORD PTR DS:[addr_int_keep_process],OFFSET DOSGROUP:Stay_resident + + PUSH CS + POP DS + PUSH CS + POP ES +ASSUME DS:DOSGROUP,ES:DOSGROUP +; +; Initialize the jump table for the sharer... +; + MOV DI,OFFSET DOSGroup:JShare + MOV AX,CS + MOV CX,15 +JumpTabLoop: + ADD DI,2 ; skip offset + STOSW ; drop in segment + LOOP JumpTabLoop + + MOV AX,OFFSET DOSGROUP:INITBLOCK + ADD AX,0Fh ; round to a paragraph + MOV CL,4 + SHR AX,CL + MOV DI,DS + ADD DI,AX + INC DI + MOV [CurrentPDB],DI + PUSH BP + PUSH DX ; Save COMMAND address + MOV AX,[ENDMEM] + MOV DX,DI + + invoke SETMEM ; Basic Header +ASSUME DS:NOTHING,ES:NOTHING + PUSH CS + POP DS +ASSUME DS:DOSGROUP + MOV DI,PDB_JFN_Table + XOR AX,AX + STOSW + STOSB ; 0,1 and 2 are CON device + MOV AL,0FFH + MOV CX,FilPerProc - 3 + REP STOSB ; Rest are unused + PUSH CS + POP ES +ASSUME ES:DOSGROUP + MOV WORD PTR [sft_addr+2],DS ; Must be set to print messages + +; After this points the char device functions for CON will work for +; printing messages + + IF (NOT IBM) OR (DEBUG) + IF NOT ALTVECT + MOV SI,OFFSET DOSGROUP:HEADER +OUTMES: + LODS CS:BYTE PTR [SI] + CMP AL,"$" + JZ OUTDONE + invoke OUT + JMP SHORT OUTMES +OUTDONE: + PUSH CS ; OUT stomps on segments + POP DS + PUSH CS + POP ES + ENDIF + ENDIF + +;F.C Modification start DOS 3.3 + MOV SI,OFFSET DOSGROUP:COUNTRY_CDPG ;F.C. for DOS 3.3 country info + ; table address + MOV WORD PTR ES:[SI.ccUcase_ptr + 2],ES ; initialize double word + MOV WORD PTR ES:[SI.ccFileUcase_ptr + 2],ES ; pointers with DOSGROUP + MOV WORD PTR ES:[SI.ccFileChar_ptr + 2],ES + MOV WORD PTR ES:[SI.ccCollate_ptr + 2],ES + MOV WORD PTR ES:[SI.ccMono_ptr + 2],ES + MOV WORD PTR ES:[SI.ccDBCS_ptr + 2],ES ; 2/16/KK + + MOV SI,OFFSET DOSGROUP:SysInitTable + MOV WORD PTR ES:[SI.SYSI_Country_Tab + 2],ES + MOV WORD PTR ES:[SI.SYSI_InitVars + 2],ES + + MOV WORD PTR ES:[BUFFHEAD+2],ES ;LB. DOS 4.00 buffer head pointer ;AN000; + MOV SI,OFFSET DOSGROUP:HASHINITVAR ;LB. points to Hashinitvar ;AN000; + MOV WORD PTR ES:[BUFFHEAD],SI ;LB. ;AN000; + MOV WORD PTR ES:[BUF_HASH_PTR+2],ES ;LB. ;AN000; + MOV SI,OFFSET DOSGROUP:Hash_Temp ;LB. ;AN000; + MOV WORD PTR ES:[BUF_HASH_PTR],SI ;LB. ;AN000; + + MOV SI,OFFSET DOSGROUP:FastOpenTable + MOV WORD PTR ES:[SI.FASTOPEN_NAME_CACHING + 2],ES + MOV ES:[FETCHI_TAG],22642 ; TAG for IBM, + ; Fetchi's serial # = 822642 + MOV WORD PTR ES:[IFS_DOS_CALL+2],ES ;IFS. ;AN000; + MOV SI,OFFSET DOSGROUP:IFS_DOSCALL ;IFS. ;AN000; + MOV WORD PTR ES:[IFS_DOS_CALL],SI ;IFS. ;AN000; + + MOV DI,OFFSET DOSGROUP:SWAP_START ;IFS. ;AN000; + MOV CX,OFFSET DOSGROUP:SWAP_END ;IFS. ;AN000; + MOV DX,OFFSET DOSGroup:Swap_Always ;IFS. ;AN000; + MOV BP,CX ;IFS. ;AN000; + SUB BP,DI ;IFS. ;AN000; + SHR BP,1 ;IFS. div by 2, remainder in carry ;AN000; + ADC BP,0 ;IFS. div by 2 + round up ;AN000; + SHL BP,1 ;IFS. round up to 2 boundary. ;AN000; + MOV ES:[SWAP_AREA_LEN],BP ;IFS. ;AN000; + + SUB CX,DX ;IFS. ;AN000; + SUB DX,DI ;IFS. ;AN000; + SHR CX,1 ;IFS. div by 2, remainder in carry ;AN000; + ADC CX,0 ;IFS. div by 2 + round up ;AN000; + SHL CX,1 ;IFS. round up to 2 boundary. ;AN000; + MOV ES:[SWAP_IN_DOS_LEN],CX ;IFS. ;AN000; + MOV WORD PTR ES:[SWAP_ALWAYS_AREA],DI ;IFS. ;AN000; + MOV WORD PTR ES:[SWAP_ALWAYS_AREA+2],ES ;IFS. ;AN000; + OR DX,8000H ;IFS. ;AN000; + MOV ES:[SWAP_ALWAYS_AREA_LEN],DX ;IFS. ;AN000; + MOV DI,OFFSET DOSGroup:Swap_Always ;IFS. ;AN000; + MOV WORD PTR ES:[SWAP_IN_DOS],DI ;IFS. ;AN000; + MOV WORD PTR ES:[SWAP_IN_DOS+2],ES ;IFS. ;AN000; + + + +;F.C Modification end DOS 3.3 + +; Move the FATs into position + POP DX ; Restore COMMAND address + POP BP + POP CX ; True address of free memory + MOV SI,OFFSET DOSGROUP:MEMSTRT ; Place to move DPBs from + MOV DI,WORD PTR [DPBHEAD] ; Place to move DPBs to + SUB CX,DI ; Total length of DPBs + CMP DI,SI + JBE MOVJMP ; Are we moving to higher or lower memory? + DEC CX ; Move backwards to higher memory + ADD DI,CX + ADD SI,CX + INC CX + STD +MOVJMP: + MOV ES,BP +ASSUME ES:DOSGROUP + JMP MOVDPB + +CHARINIT: +ASSUME DS:NOTHING,ES:NOTHING +; DS:SI Points to device header + MOV [DEVCALL.REQLEN],DINITHL + MOV [DEVCALL.REQUNIT],0 + MOV [DEVCALL.REQFUNC],DEVINIT + MOV [DEVCALL.REQSTAT],0 + PUSH ES + PUSH BX + PUSH AX + MOV BX,OFFSET DOSGROUP:DEVCALL + PUSH CS + POP ES + invoke DEVIOCALL2 + POP AX + POP BX + POP ES + RET + +Public MSINI002S,MSINI002E +MSINI002S label byte + + DB 100H DUP(?) +INITSTACK LABEL BYTE + DW ? + DB "ADD SPECIAL ENTRIES",0 ;AN007 tiltle +;The following entries don't expect version 4.0 +;The entry format: name_length, name, expected version, fake count +;fake_count: ff means the version will be reset when Abort or Exec is encountered +; n means the version will be reset after n DOS version calls are issued +; +Version_Fake_Table: ;AN007 starting address for special + DB 12,"IBMCACHE.COM",3,40,255 ;AN007 ibmcache 1 + DB 12,"IBMCACHE.SYS",3,40,255 ;AN007 ibmcache 2 + DB 12,"DXMA0MOD.SYS",3,40,255 ;AN007 lan support 3 + DB 10,"WIN200.BIN" ,3,40,4 ;AN008 windows 4 + DB 9,"PSCPG.COM" ,3,40,255 ;AN008 vittoria 5 + DB 11,"DCJSS02.EXE" ,3,40,255 ;AN008 netview 6 + DB 8,"ISAM.EXE" ,3,40,255 ;AN008 basic 7 + DB 9,"ISAM2.EXE" ,3,40,255 ;AN008 basic 8 + DB 12,"DFIA0MOD.SYS",3,40,255 ;AN008 lan support 9 + DB 20 dup(0) ;AN007 + +MEMSTRT LABEL WORD +MSINI002E label byte +ADJFAC EQU MEMSTRT-SYSBUF + +LAST ENDS diff --git a/v4.0/src/DOS/MSIOCTL.ASM b/v4.0/src/DOS/MSIOCTL.ASM new file mode 100644 index 0000000..2117f41 --- /dev/null +++ b/v4.0/src/DOS/MSIOCTL.ASM @@ -0,0 +1,5 @@ +; SCCSID = @(#)IBMIOCTL.INC 1.1 85/04/10 +IBM EQU 0FFFFH ;TRUE + +INCLUDE IOCTL.INC + SCCSID = @(#)IBMIOCTL.INC 1.1 85/04/10 diff --git a/v4.0/src/DOS/MSPROC.ASM b/v4.0/src/DOS/MSPROC.ASM new file mode 100644 index 0000000..542874f --- /dev/null +++ b/v4.0/src/DOS/MSPROC.ASM @@ -0,0 +1,15 @@ +; SCCSID = @(#)ibmproc.asm 1.1 85/04/10 +; +; Pseudo EXEC system call for DOS +; + +.xlist +.xcref +include mssw.asm +.cref +.list + +TITLE IBMPROC - process maintenance +NAME IBMPROC + +include proc.asm diff --git a/v4.0/src/DOS/MSSW.ASM b/v4.0/src/DOS/MSSW.ASM new file mode 100644 index 0000000..db8eb11 --- /dev/null +++ b/v4.0/src/DOS/MSSW.ASM @@ -0,0 +1,27 @@ +; SCCSID = @(#)ibmsw.asm 1.1 85/04/10 + +include version.inc + +IBM EQU ibmver +WANG EQU FALSE + +; Set this switch to cause DOS to move itself to the end of memory +HIGHMEM EQU FALSE + +; Turn on switch below to allow testing disk code with DEBUG. It sets +; up a different stack for disk I/O (functions > 11) than that used for +; character I/O which effectively makes the DOS re-entrant. + + IF IBM +ESCCH EQU 0 ; character to begin escape seq. +CANCEL EQU 27 ;Cancel with escape +TOGLPRN EQU TRUE ;One key toggles printer echo +ZEROEXT EQU TRUE + ELSE +ESCCH EQU 1BH +CANCEL EQU "X"-"@" ;Cancel with Ctrl-X +TOGLPRN EQU FALSE ;Separate keys for printer echo on + ;and off +ZEROEXT EQU TRUE + ENDIF + \ No newline at end of file diff --git a/v4.0/src/DOS/MS_CODE.ASM b/v4.0/src/DOS/MS_CODE.ASM new file mode 100644 index 0000000..1bdd4af --- /dev/null +++ b/v4.0/src/DOS/MS_CODE.ASM @@ -0,0 +1,614 @@ +; SCCSID = @(#)mscode.asm 1.2 85/07/23 +; +; MSCODE.ASM -- MSDOS code +; + +.xlist +.xcref +include dossym.inc +include devsym.inc +include dosseg.asm +include ifssym.inc +include fastopen.inc +include fastxxxx.inc +.cref +.list + +AsmVars + +CODE SEGMENT BYTE PUBLIC 'CODE' + +ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + + I_need InDos,BYTE ; TRUE => we are in dos, no interrupt + I_need OpenBuf,128 ; temp name buffer + I_need ExtErr,WORD ; extended error code + I_need User_SS,WORD ; stack segment from user + I_need User_SP,WORD ; stack pointer from user + I_need DskStack,BYTE ; stack segment inside DOS + I_need ThisCDS,DWORD ; Currently referenced CDS pointer + I_need ThisDPB,DWORD ; Currently referenced DPB pointer + I_need Err_Table_21 ; allowed return map table for errors + I_need FailErr,BYTE ; TRUE => system call is being failed + I_need ExtErr_Action,BYTE ; recommended action + I_need ExtErr_Class,BYTE ; error classification + I_need ExtErr_Locus,BYTE ; error location + I_need I21_Map_E_Tab,BYTE ; mapping extended error table + I_need User_In_AX,WORD ; initial input user AX + I_need FOO,WORD ; return address for dos 2f dispatch + I_need DTAB,WORD ; dos 2f dispatch table + I_need HIGH_SECTOR,WORD ; >32mb + I_need IFS_DRIVER_ERR,WORD ; >32mb + I_need FastOpenFlg,BYTE ; + I_need FastSeekFlg,BYTE ; + I_need CURSC_DRIVE,BYTE ; + +BREAK + +procedure SNULDEV,FAR +ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + OR ES:[BX.REQSTAT],STDON ; Set done bit +entry INULDEV + RET ; MUST NOT BE A RETURN! +EndProc SNULDEV + +BREAK + + +TABLE SEGMENT +Public MSC001S,MSC001E +MSC001S label byte + IF IBM +; Codes returned by BIOS +ERRIN: + DB 2 ; NO RESPONSE + DB 6 ; SEEK FAILURE + DB 12 ; GENERAL ERROR + DB 4 ; BAD CRC + DB 8 ; SECTOR NOT FOUND + DB 0 ; WRITE ATTEMPT ON WRITE-PROTECT DISK +ERROUT: +; DISK ERRORS RETURNED FROM INT 25 and 26 + DB 80H ; NO RESPONSE + DB 40H ; Seek failure + DB 2 ; Address Mark not found + DB 10H ; BAD CRC + DB 4 ; SECTOR NOT FOUND + DB 3 ; WRITE ATTEMPT TO WRITE-PROTECT DISK + +NUMERR EQU $-ERROUT + ENDIF +MSC001E label byte + +TABLE ENDS + +; AbsSetup - setup for abs disk functions + +Procedure AbsSetup,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup + INC INDOS + STI + CLD + PUSH DS + Context DS + CALL GETBP + JC errdriv ;PM. error drive ;AN000; + MOV ES:[BP.dpb_free_cnt],-1 ; do not trust user at all. +errdriv: + POP DS +ASSUME DS:NOTHING + retc + + MOV [HIGH_SECTOR],0 ;>32mb from API ;AN000; + CALL RW32_CONVERT ;>32mb convert 32bit format to 16bit ;AN000; + retc + + invoke SET_RQ_SC_PARMS ;LB. set up SC parms ;AN000; + PUSH DS + PUSH SI + PUSH AX + Context DS + MOV SI,OFFSET DOSGROUP:OPENBUF + MOV [SI],AL + ADD BYTE PTR [SI],"A" + MOV WORD PTR [SI+1],003AH ; ":",0 + MOV AX,0300H + CLC + INT int_IBM ; Will set carry if shared + POP AX + POP SI + POP DS +ASSUME DS:NOTHING + retnc + MOV ExtErr,error_not_supported + return +EndProc AbsSetup + +; Interrupt 25 handler. Performs absolute disk read. +; Inputs: AL - 0-based drive number +; DS:BX point to destination buffer +; CX number of logical sectors to read +; DX starting logical sector number (0-based) +; Outputs: Original flags still on stack +; Carry set +; AH error from BIOS +; AL same as low byte of DI from INT 24 + + procedure ABSDRD,FAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING + + CLI + MOV [user_SS],SS + MOV [user_SP],SP + PUSH CS + POP SS +ASSUME SS:DOSGROUP + MOV SP,OFFSET DOSGROUP:DSKSTACK + invoke Save_World ;>32mb save all regs ;AN000; + PUSH ES + CALL AbsSetup + JC ILEAVE +if not ibmcopyright +; Here is a gross temporary fix to get around a serious design flaw in +; the secondary cache. The secondary cache does not check for media +; changed (it should). Hence, you can change disks, do an absolute +; read, and get data from the previous disk. To get around this, +; we just won't use the secondary cache for absolute disk reads. +; -mw 8/5/88 + EnterCrit critDisk + MOV [CURSC_DRIVE],-1 ; invalidate SC ;AN000; + LeaveCrit critDisk +endif + invoke DSKREAD +TLEAVE: + JZ ILEAVE + + IF IBM +; Translate the error code to ancient 1.1 codes + PUSH ES + PUSH CS + POP ES + XOR AH,AH ; Nul error code + MOV CX,NUMERR ; Number of possible error conditions + MOV DI,OFFSET DOSGROUP:ERRIN ; Point to error conditions + REPNE SCASB + JNZ LEAVECODE ; Not found + MOV AH,ES:[DI+NUMERR-1] ; Get translation +LEAVECODE: + POP ES + ENDIF + MOV [IFS_DRIVER_ERR],AX ;>32mb save error + STC +ILEAVE: + POP ES + invoke Restore_World ;>32mb ;AN000; + CLI + DEC INDOS + MOV SS,[user_SS] +ASSUME SS:NOTHING + MOV SP,[user_SP] + MOV AX,[IFS_DRIVER_ERR] ;>32mb restore error ;AN000; + STI + RET ; This must not be a RETURN! +EndProc ABSDRD + +; Interrupt 26 handler. Performs absolute disk write. +; Inputs: AL - 0-based drive number +; DS:BX point to source buffer +; CX number of logical sectors to write +; DX starting logical sector number (0-based) +; Outputs: Original flags still on stack +; Carry set +; AH error from BIOS +; AL same as low byte of DI from INT 24 + + procedure ABSDWRT,FAR +ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + + CLI + MOV [user_SS],SS + MOV [user_SP],SP + PUSH CS + POP SS +ASSUME SS:DOSGROUP + MOV SP,OFFSET DOSGROUP:DSKSTACK + invoke Save_World ;>32mb save all regs ;AN000; + + PUSH ES + CALL AbsSetup + JC ILEAVE + + EnterCrit critDisk + MOV [CURSC_DRIVE],-1 ; invalidate SC ;AN000; + CALL Fastxxx_Purge ; purge fatopen ;AN000; + LeaveCrit critDisk + + invoke DSKWRITE + JMP TLEAVE +EndProc ABSDWRT + +; Inputs: +; AL = Logical unit number (A = 0) +; Function: +; Find Drive Parameter Block +; Outputs: +; ES:BP points to DPB +; [THISDPB] = ES:BP +; Carry set if unit number bad or unit is a NET device. +; Later case sets extended error error_I24_not_supported +; No other registers altered + +Procedure GETBP,NEAR + DOSAssume CS,,"GetBP" + ASSUME ES:NOTHING + + PUSH AX + ADD AL,1 ; No increment; need carry flag + JC SkipGet + invoke GetThisDrv + JNC SkipGet ;PM. good drive ;AN000; + XOR AH,AH ;DCR. ax= error code ;AN000; + CMP AX,error_not_dos_disk ;DCR. is unknown media ? ;AN000; + JZ SkipGet ;DCR. yes, let it go ;AN000; + STC ;DCR. ;AN000; + MOV ExtErr,AX ;PM. invalid drive or Non DOS drive ;AN000; + MOV [IFS_DRIVER_ERR],0201H ;PM. other errors/unknown unit ;AN000; +SkipGet: + POP AX + retc + LES BP,[THISCDS] + TEST ES:[BP.curdir_flags],curdir_isnet ; Clears carry + JZ GETBP_CDS + LES BP,ES:[BP.curdir_ifs_hdr] ;IFS. if remote file ;AN000; + TEST ES:[BP.ifs_attribute],IFSREMOTE ;IFS. ;AN000; + LES BP,[THISCDS] + JZ GETBP_CDS ;IFS. then error ;AN000; + MOV ExtErr,error_not_supported + STC + return + +GETBP_CDS: + LES BP,ES:[BP.curdir_devptr] + + entry GOTDPB + DOSAssume CS,,"GotDPB" +; Load THISDPB from ES:BP + + MOV WORD PTR [THISDPB],BP + MOV WORD PTR [THISDPB+2],ES + return +EndProc GetBP + +BREAK + +ASSUME SS:DOSGROUP + +; +; These are the general system call exit mechanisms. All internal system +; calls will transfer (jump) to one of these at the end. Their sole purpose +; is to set the user's flags and set his AX register for return. +; + +procedure SYS_RETURN,NEAR + ASSUME DS:NOTHING,ES:NOTHING +entry SYS_RET_OK + invoke FETCHI_CHECK ; TAG checking for FETCHI + invoke get_user_stack + AND [SI.user_F],NOT f_Carry ; turn off user's carry flag + JMP SHORT DO_RET ; carry is now clear + +entry SYS_RET_ERR + XOR AH,AH ; hack to allow for smaller error rets + invoke ETAB_LK ; Make sure code is OK, EXTERR gets set + CALL ErrorMap +entry From_GetSet + invoke get_user_stack + OR [SI.user_F],f_Carry ; signal carry to user + STC ; also, signal internal error +DO_RET: + MOV [SI.user_AX],AX ; Really only sets AH + return + + entry FCB_RET_OK + entry CPMFunc + XOR AL,AL + return + + entry FCB_RET_ERR + XOR AH,AH + mov exterr,AX + CALL ErrorMap + MOV AL,-1 + return + + entry errorMap + PUSH SI + MOV SI,OFFSET DOSGROUP:ERR_TABLE_21 + CMP [FAILERR],0 ; Check for SPECIAL case. + JZ EXTENDED_NORMAL ; All is OK. + MOV [EXTERR],error_FAIL_I24 ; Ooops, this is the REAL reason + MOV SI,OFFSET DOSGROUP:ERR_TABLE_21 +EXTENDED_NORMAL: + invoke CAL_LK ; Set CLASS,ACTION,LOCUS for EXTERR + POP SI + return + +EndProc SYS_RETURN + +; Inputs: +; SI is OFFSET in DOSGROUP of CLASS,ACTION,LOCUS Table to use +; (DS NEED not be DOSGROUP) +; [EXTERR] is set with error +; Function: +; Look up and set CLASS ACTION and LOCUS values for GetExtendedError +; Outputs: +; [EXTERR_CLASS] set +; [EXTERR_ACTION] set +; [EXTERR_LOCUS] set (EXCEPT on certain errors as determined by table) +; Destroys SI, FLAGS + + procedure CAL_LK,NEAR +ASSUME DS:NOTHING,ES:NOTHING + + PUSH DS + PUSH AX + PUSH BX + Context DS ; DS:SI -> Table + MOV BX,[EXTERR] ; Get error in BL +TABLK1: + LODSB + CMP AL,0FFH + JZ GOT_VALS ; End of table + CMP AL,BL + JZ GOT_VALS ; Got entry + ADD SI,3 ; Next table entry + JMP TABLK1 + +GOT_VALS: + LODSW ; AL is CLASS, AH is ACTION + CMP AH,0FFH + JZ NO_SET_ACT + MOV [EXTERR_ACTION],AH ; Set ACTION +NO_SET_ACT: + CMP AL,0FFH + JZ NO_SET_CLS + MOV [EXTERR_CLASS],AL ; Set CLASS +NO_SET_CLS: + LODSB ; Get LOCUS + CMP AL,0FFH + JZ NO_SET_LOC + MOV [EXTERR_LOCUS],AL +NO_SET_LOC: + POP BX + POP AX + POP DS + return +EndProc CAL_LK + +; Inputs: +; AX is error code +; [USER_IN_AX] has AH value of system call involved +; Function: +; Make sure error code is appropriate to this call. +; Outputs: +; AX MAY be mapped error code +; [EXTERR] = Input AX +; Destroys ONLY AX and FLAGS + + procedure ETAB_LK,NEAR +ASSUME DS:NOTHING,ES:NOTHING + + PUSH DS + PUSH SI + PUSH CX + PUSH BX + Context DS + MOV [EXTERR],AX ; Set EXTERR with "real" error + MOV SI,OFFSET DOSGROUP:I21_MAP_E_TAB + MOV BH,AL ; Real code to BH + MOV BL,BYTE PTR [USER_IN_AX + 1] ; Sys call to BL +TABLK2: + LODSW + CMP AL,0FFH ; End of table? + JZ NOT_IN_TABLE ; Yes + CMP AL,BL ; Found call? + JZ GOT_CALL ; Yes + XCHG AH,AL ; Count to AL + XOR AH,AH ; Make word for add + ADD SI,AX ; Next table entry + JMP TABLK2 + +NOT_IN_TABLE: + MOV AL,BH ; Restore original code + JMP SHORT NO_MAP + +GOT_CALL: + MOV CL,AH + XOR CH,CH ; Count of valid err codes to CX +CHECK_CODE: + LODSB + CMP AL,BH ; Code OK? + JZ NO_MAP ; Yes + LOOP CHECK_CODE +NO_MAP: + XOR AH,AH ; AX is now valid code + POP BX + POP CX + POP SI + POP DS + return + +EndProc ETAB_LK + +BREAK + +IF installed + +; +; SetBad sets up info for bad functions +; +Procedure SetBad,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + MOV AX,error_invalid_function ; ALL NET REQUESTS get inv func + MOV ExtErr_LOCUS,errLoc_UNK + STC + ret +EndProc SetBad +; +; BadCall is the initial routine for bad function calls +; +procedure BadCall,FAR + call SetBad + ret +EndProc BadCall +; +; OKCall always sets carry to off. +; +Procedure OKCall,FAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + CLC + ret +EndProc OKCall + +; INT 2F handler works as follows: +; PUSH AX +; MOV AX,multiplex:function +; INT 2F +; POP ... +; The handler itself needs to make the AX available for the various routines. + +PUBLIC Int2F +INT2F PROC FAR + +INT2FNT: + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + STI + CMP AH,multNET + JNZ INT2FSHR +TestInstall: + OR AL,AL + JZ Leave2F +BadFunc: + CALL SetBad + entry Leave2F + RET 2 ; long return + clear flags off stack + +INT2FSHR: + CMP AH,multSHARE ; is this a share request + JZ TestInstall ; yes, check for installation + +INT2FNLS: + CMP AH,NLSFUNC ; is this a DOS 3.3 NLSFUNC request + JZ TestInstall ; yes check for installation + +INT2FDOS: + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + CMP AH,multDOS + JZ DispatchDOS + IRET ; This assume that we are at the head + ; of the list +INT2F ENDP + +DispatchDOS: + PUSH FOO ; push return address + PUSH DTab ; push table address + PUSH AX ; push index + PUSH BP + MOV BP,SP +; stack looks like: +; 0 BP +; 2 DISPATCH +; 4 TABLE +; 6 RETURN +; 8 LONG-RETURN +; c FLAGS +; e AX + + MOV AX,[BP+0Eh] ; get AX value + POP BP + Invoke TableDispatch + JMP BadFunc ; return indicates invalid function + +Procedure INT2F_etcetera,NEAR + entry DosGetGroup + PUSH CS + POP DS + return + + entry DOSInstall + MOV AL,0FFh + return +EndProc INT2F_etcetera + +ENDIF +;Input: same as ABSDRD and ABSDWRT +; ES:BP -> DPB +;Functions: convert 32bit absolute RW input parms to 16bit input parms +;Output: carry set when CX=-1 and drive is less then 32mb +; carry clear, parms ok +; +Procedure RW32_CONVERT,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + CMP CX,-1 ;>32mb new format ? ;AN000; + JZ new32format ;>32mb yes ;AN000; + PUSH AX ;>32mb save ax ;AN000; + PUSH DX ;>32mb save dx ;AN000; + MOV AX,ES:[BP.dpb_max_cluster] ;>32mb get max cluster # ;AN000; + MOV DL,ES:[BP.dpb_cluster_mask] ;>32mb ;AN000; + CMP DL,0FEH ;>32mb removable ? ;AN000; + JZ letold ;>32mb yes ;AN000; + INC DL ;>32mb ;AN000; + XOR DH,DH ;>32mb dx = sector/cluster ;AN000; + MUL DX ;>32mb dx:ax= max sector # ;AN000; + OR DX,DX ;>32mb > 32mb ? ;AN000; +letold: + POP DX ;>32mb retore dx ;AN000; + POP AX ;>32mb restore ax ;AN000; + JZ old_style ;>32mb no ;AN000; + MOV [IFS_DRIVER_ERR],0207H ;>32mb error ;AN000; + STC ;>32mb ;AN000; + return ;>32mb ;AN000; +new32format: + MOV DX,WORD PTR [BX.SECTOR_RBA+2];>32mb ;AN000; + MOV [HIGH_SECTOR],DX ;>32mb ;AN000; + MOV DX,WORD PTR [BX.SECTOR_RBA] ;>32mb ;AN000; + MOV CX,[BX.ABS_RW_COUNT] ;>32mb ;AN000; + LDS BX,[BX.BUFFER_ADDR] ;>32mb ;AN000; +old_style: ;>32mb ;AN000; + CLC ;>32mb ;AN000; + return ;>32mb ;AN000; +EndProc RW32_CONVERT + + +;Input: None +;Functions: Purge Fastopen/seek Cache Buffers +;Output: None +; +; +Procedure Fastxxx_Purge,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + PUSH AX ; save regs. ;AN000; + PUSH SI ;AN000; + PUSH DX ;AN000; + TEST FastSeekflg,Fast_yes ; fastseek installed ? ;AN000; + JZ topen ; no ;AN000; + MOV AH,FastSeek_ID ; set fastseek id ;AN000; + JMP SHORT dofast ; ;AN000; +topen: + TEST FastOpenflg,Fast_yes ; fastopen installed ? ;AN000; + JZ nofast ; no ;AN000; + MOV AH,FastOpen_ID ; set fastseek installed ;AN000; +dofast: + MOV AL,FONC_purge ; purge ;AN000; + MOV DL,ES:[BP.dpb_drive] ; set up drive number ;AN000; + invoke Fast_Dispatch ; call fastopen/seek ;AN000; +nofast: + POP DX ;AN000; + POP SI ; restore regs ;AN000; + POP AX ; ;AN000; + + return ; exit ;AN000; +EndProc Fastxxx_Purge + +CODE ENDS + \ No newline at end of file diff --git a/v4.0/src/DOS/MS_TABLE.ASM b/v4.0/src/DOS/MS_TABLE.ASM new file mode 100644 index 0000000..b5ffac7 --- /dev/null +++ b/v4.0/src/DOS/MS_TABLE.ASM @@ -0,0 +1,710 @@ +; SCCSID = @(#)mstable.asm 1.3 85/07/25 +; Revision history: +; A000 version 4.0 Jan. 1988 +; A001 DCR 486 - Share installation for >32mb drives +; A006 DCR 503 - fake version for IBMCACHE +; A008 PTM 4070 - fake version for MS WINDOWS +.xlist +.xcref +include dosseg.asm +include EA.inc ;AN000;; for Extended Attributes +include fastopen.inc ;AN000;; for Extended Attributes +include dossym.inc +.cref +.list + + AsmVars + +TABLE SEGMENT BYTE PUBLIC 'TABLE' +TableZero LABEL BYTE + + PUBLIC MSVERS +PUBLIC MSTAB001s,MSTAB001e +MSTAB001S label byte + +MSVERS EQU THIS WORD ; MS-DOS version in hex for $GET_VERSION +MSMAJOR DB MAJOR_VERSION +MSMINOR DB MINOR_VERSION + + I_am YRTAB,8,<200,166,200,165,200,165,200,165> ; [SYSTEM] + I_am MONTAB,12,<31,28,31,30,31,30,31,31,30,31,30,31> ; [SYSTEM] + +; +; This is the error code mapping table for INT 21 errors. This table defines +; those error codes which are "allowed" for each system call. If the error +; code ABOUT to be returned is not "allowed" for the call, the correct action +; is to return the "real" error via Extended error, and one of the allowed +; errors on the actual call. +; +; The table is organized as follows: +; +; Each entry in the table is of variable size, but the first +; two bytes are always: +; +; Call#,Cnt of bytes following this byte +; +; EXAMPLE: +; Call 61 (OPEN) +; +; DB 61,5,12,3,2,4,5 +; +; 61 is the AH INT 21 call value for OPEN. +; 5 indicates that there are 5 bytes after this byte (12,3,2,4,5). +; Next five bytes are those error codes which are "allowed" on OPEN. +; The order of these values is not important EXCEPT FOR THE LAST ONE (in +; this case 5). The last value will be the one returned on the call if +; the "real" error is not one of the allowed ones. +; +; There are a number of calls (for instance all of the FCB calls) for which +; there is NO entry. This means that NO error codes are returned on this +; call, so set up an Extended error and leave the current error code alone. +; +; The table is terminated by a call value of 0FFh + +PUBLIC I21_MAP_E_TAB +I21_MAP_E_TAB LABEL BYTE + DB International,2,error_invalid_function,error_file_not_found + DB MKDir,3,error_path_not_found,error_file_not_found,error_access_denied + DB RMDir,4,error_current_directory,error_path_not_found + DB error_file_not_found,error_access_denied + DB CHDir,2,error_file_not_found,error_path_not_found + DB Creat,4,error_path_not_found,error_file_not_found + DB error_too_many_open_files + DB error_access_denied + DB Open,6,error_path_not_found,error_file_not_found,error_invalid_access + DB error_too_many_open_files + DB error_not_dos_disk,error_access_denied + DB Close,1,error_invalid_handle + DB Read,2,error_invalid_handle,error_access_denied + DB Write,2,error_invalid_handle,error_access_denied + DB Unlink,3,error_path_not_found,error_file_not_found,error_access_denied + DB LSeek,2,error_invalid_handle,error_invalid_function + DB CHMod,4,error_path_not_found,error_file_not_found,error_invalid_function + DB error_access_denied + DB IOCtl,5,error_invalid_drive,error_invalid_data,error_invalid_function + DB error_invalid_handle,error_access_denied + DB XDup,2,error_invalid_handle,error_too_many_open_files + DB XDup2,2,error_invalid_handle,error_too_many_open_files + DB Current_Dir,2,error_not_DOS_disk,error_invalid_drive + DB Alloc,2,error_arena_trashed,error_not_enough_memory + DB Dealloc,2,error_arena_trashed,error_invalid_block + DB Setblock,3,error_arena_trashed,error_invalid_block,error_not_enough_memory + DB Exec,8,error_path_not_found,error_invalid_function,error_file_not_found + DB error_too_many_open_files,error_bad_format,error_bad_environment + DB error_not_enough_memory,error_access_denied + DB Find_First,3,error_path_not_found,error_file_not_found,error_no_more_files + DB Find_Next,1,error_no_more_files + DB Rename,5,error_not_same_device,error_path_not_found,error_file_not_found + DB error_current_directory,error_access_denied + DB File_Times,4,error_invalid_handle,error_not_enough_memory + DB error_invalid_data,error_invalid_function + DB AllocOper,1,error_invalid_function + DB CreateTempFile,4,error_path_not_found,error_file_not_found + DB error_too_many_open_files,error_access_denied + DB CreateNewFile,5,error_file_exists,error_path_not_found + DB error_file_not_found,error_too_many_open_files,error_access_denied + DB LockOper,4,error_invalid_handle,error_invalid_function + DB error_sharing_buffer_exceeded,error_lock_violation + DB GetExtCntry,2,error_invalid_function,error_file_not_found ;DOS 3.3 + DB GetSetCdPg,2,error_invalid_function,error_file_not_found ;DOS 3.3 + DB Commit,1,error_invalid_handle ;DOS 3.3 + DB ExtHandle,3,error_too_many_open_files,error_not_enough_memory + DB error_invalid_function + DB ExtOpen,10 + DB error_path_not_found,error_file_not_found,error_invalid_access + DB error_too_many_open_files,error_file_exists,error_not_enough_memory + DB error_not_dos_disk,error_invalid_data + DB error_invalid_function,error_access_denied + DB GetSetMediaID,4,error_invalid_drive,error_invalid_data + DB error_invalid_function,error_access_denied + DB 0FFh + +; +; The following table defines CLASS ACTION and LOCUS info for the INT 21H +; errors. Each entry is 4 bytes long: +; +; Err#,Class,Action,Locus +; +; A value of 0FFh indicates a call specific value (ie. should already +; be set). AN ERROR CODE NOT IN THE TABLE FALLS THROUGH TO THE CATCH ALL AT +; THE END, IT IS ASSUMES THAT CLASS, ACTION, LOCUS IS ALREADY SET. +ErrTab Macro err,class,action,locus +ifidn ,<0FFh> + DB error_&err,errCLASS_&class,errACT_&action,0FFh +ELSE + DB error_&err,errCLASS_&class,errACT_&action,errLOC_&locus +ENDIF +ENDM + +PUBLIC ERR_TABLE_21 +ERR_TABLE_21 LABEL BYTE + ErrTab invalid_function, Apperr, Abort, 0FFh + ErrTab file_not_found, NotFnd, User, Disk + ErrTab path_not_found, NotFnd, User, Disk + ErrTab too_many_open_files, OutRes, Abort, Unk + ErrTab access_denied, Auth, User, 0FFh + ErrTab invalid_handle, Apperr, Abort, Unk + ErrTab arena_trashed, Apperr, Panic, Mem + ErrTab not_enough_memory, OutRes, Abort, Mem + ErrTab invalid_block, Apperr, Abort, Mem + ErrTab bad_environment, Apperr, Abort, Mem + ErrTab bad_format, BadFmt, User, Unk + ErrTab invalid_access, Apperr, Abort, Unk + ErrTab invalid_data, BadFmt, Abort, Unk + ErrTab invalid_drive, NotFnd, User, Disk + ErrTab current_directory, Auth, User, Disk + ErrTab not_same_device, Unk, User, Disk + ErrTab no_more_files, NotFnd, User, Disk + ErrTab file_exists, Already, User, Disk + ErrTab sharing_violation, Locked, DlyRet, Disk + ErrTab lock_violation, Locked, DlyRet, Disk + ErrTab out_of_structures, OutRes, Abort, 0FFh + ErrTab invalid_password, Auth, User, Unk + ErrTab cannot_make, OutRes, Abort, Disk + ErrTab Not_supported, BadFmt, User, Net + ErrTab Already_assigned, Already, User, Net + ErrTab Invalid_Parameter, BadFmt, User, Unk + ErrTab FAIL_I24, Unk, Abort, Unk + ErrTab Sharing_buffer_exceeded,OutRes, Abort, Mem + ErrTab Handle_EOF, OutRes, Abort, Unk ;AN000; + ErrTab Handle_DISK_FULL, OutRes, Abort, Unk ;AN000; + ErrTab sys_comp_not_loaded, Unk, Abort, Disk ;AN001; + DB 0FFh, 0FFH, 0FFH, 0FFh + +; +; The following table defines CLASS ACTION and LOCUS info for the INT 24H +; errors. Each entry is 4 bytes long: +; +; Err#,Class,Action,Locus +; +; A Locus value of 0FFh indicates a call specific value (ie. should already +; be set). AN ERROR CODE NOT IN THE TABLE FALLS THROUGH TO THE CATCH ALL AT +; THE END. + +PUBLIC ERR_TABLE_24 +ERR_TABLE_24 LABEL BYTE + ErrTab write_protect, Media, IntRet, Disk + ErrTab bad_unit, Intrn, Panic, Unk + ErrTab not_ready, HrdFail, IntRet, 0FFh + ErrTab bad_command, Intrn, Panic, Unk + ErrTab CRC, Media, Abort, Disk + ErrTab bad_length, Intrn, Panic, Unk + ErrTab Seek, HrdFail, Retry, Disk + ErrTab not_DOS_disk, Media, IntRet, Disk + ErrTab sector_not_found, Media, Abort, Disk + ErrTab out_of_paper, TempSit, IntRet, SerDev + ErrTab write_fault, HrdFail, Abort, 0FFh + ErrTab read_fault, HrdFail, Abort, 0FFh + ErrTab gen_failure, Unk, Abort, 0FFh + ErrTab sharing_violation, Locked, DlyRet, Disk + ErrTab lock_violation, Locked, DlyRet, Disk + ErrTab wrong_disk, Media, IntRet, Disk + ErrTab not_supported, BadFmt, User, Net + ErrTab FCB_unavailable, Apperr, Abort, Unk + ErrTab Sharing_buffer_exceeded,OutRes, Abort, Mem + DB 0FFh, errCLASS_Unk, errACT_Panic, 0FFh + +; +; We need to map old int 24 errors and device driver errors into the new set +; of errors. The following table is indexed by the new errors +; +Public ErrMap24 +ErrMap24 Label BYTE + DB error_write_protect ; 0 + DB error_bad_unit ; 1 + DB error_not_ready ; 2 + DB error_bad_command ; 3 + DB error_CRC ; 4 + DB error_bad_length ; 5 + DB error_Seek ; 6 + DB error_not_DOS_disk ; 7 + DB error_sector_not_found ; 8 + DB error_out_of_paper ; 9 + DB error_write_fault ; A + DB error_read_fault ; B + DB error_gen_failure ; C + DB error_gen_failure ; D RESERVED + DB error_gen_failure ; E RESERVED + DB error_wrong_disk ; F + +Public ErrMap24End +ErrMap24End LABEL BYTE + + + PUBLIC DISPATCH,MAXCALL,MAXCOM + +MAXCALL DB VAL1 +MAXCOM DB VAL2 + +; Standard Functions +DISPATCH LABEL WORD + short_addr $ABORT ; 0 0 + short_addr $STD_CON_INPUT ; 1 1 + short_addr $STD_CON_OUTPUT ; 2 2 + short_addr $STD_AUX_INPUT ; 3 3 + short_addr $STD_AUX_OUTPUT ; 4 4 + short_addr $STD_PRINTER_OUTPUT ; 5 5 + short_addr $RAW_CON_IO ; 6 6 + short_addr $RAW_CON_INPUT ; 7 7 + short_addr $STD_CON_INPUT_NO_ECHO ; 8 8 + short_addr $STD_CON_STRING_OUTPUT ; 9 9 + short_addr $STD_CON_STRING_INPUT ; 10 A + short_addr $STD_CON_INPUT_STATUS ; 11 B + short_addr $STD_CON_INPUT_FLUSH ; 12 C + short_addr $DISK_RESET ; 13 D + short_addr $SET_DEFAULT_DRIVE ; 14 E + short_addr $FCB_OPEN ; 15 F + short_addr $FCB_CLOSE ; 16 10 + short_addr $DIR_SEARCH_FIRST ; 17 11 + short_addr $DIR_SEARCH_NEXT ; 18 12 + short_addr $FCB_DELETE ; 19 13 + short_addr $FCB_SEQ_READ ; 20 14 + short_addr $FCB_SEQ_WRITE ; 21 15 + short_addr $FCB_CREATE ; 22 16 + short_addr $FCB_RENAME ; 23 17 + short_addr CPMFUNC ; 24 18 + short_addr $GET_DEFAULT_DRIVE ; 25 19 + short_addr $SET_DMA ; 26 1A + +;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; +; C A V E A T P R O G R A M M E R ; +; ; + short_addr $SLEAZEFUNC ; 27 1B + short_addr $SLEAZEFUNCDL ; 28 1C +; ; +; C A V E A T P R O G R A M M E R ; +;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; + + short_addr CPMFUNC ; 29 1D + short_addr CPMFUNC ; 30 1E +;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; +; C A V E A T P R O G R A M M E R ; +; ; + short_addr $GET_DEFAULT_DPB ; 31 1F +; ; +; C A V E A T P R O G R A M M E R ; +;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; + short_addr CPMFUNC ; 32 20 + short_addr $FCB_RANDOM_READ ; 33 21 + short_addr $FCB_RANDOM_WRITE ; 34 22 + short_addr $GET_FCB_FILE_LENGTH ; 35 23 + short_addr $GET_FCB_POSITION ; 36 24 +VAL1 = ($-DISPATCH)/2 - 1 + +; Extended Functions + short_addr $SET_INTERRUPT_VECTOR ; 37 25 +;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; +; C A V E A T P R O G R A M M E R ; +; ; + short_addr $CREATE_PROCESS_DATA_BLOCK ; 38 26 +; ; +; C A V E A T P R O G R A M M E R ; +;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; + short_addr $FCB_RANDOM_READ_BLOCK ; 39 27 + short_addr $FCB_RANDOM_WRITE_BLOCK ; 40 28 + short_addr $PARSE_FILE_DESCRIPTOR ; 41 29 + short_addr $GET_DATE ; 42 2A + short_addr $SET_DATE ; 43 2B + short_addr $GET_TIME ; 44 2C + short_addr $SET_TIME ; 45 2D + short_addr $SET_VERIFY_ON_WRITE ; 46 2E + +; Extended functionality group + short_addr $GET_DMA ; 47 2F + short_addr $GET_VERSION ; 48 30 + short_addr $Keep_Process ; 49 31 +;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; +; C A V E A T P R O G R A M M E R ; +; ; + short_addr $GET_DPB ; 50 32 +; ; +; C A V E A T P R O G R A M M E R ; +;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; + short_addr $SET_CTRL_C_TRAPPING ; 51 33 + short_addr $GET_INDOS_FLAG ; 52 34 + short_addr $GET_INTERRUPT_VECTOR ; 53 35 + short_addr $GET_DRIVE_FREESPACE ; 54 36 + short_addr $CHAR_OPER ; 55 37 + short_addr $INTERNATIONAL ; 56 38 +; XENIX CALLS +; Directory Group + short_addr $MKDIR ; 57 39 + short_addr $RMDIR ; 58 3A + short_addr $CHDIR ; 59 3B +; File Group + short_addr $CREAT ; 60 3C + short_addr $OPEN ; 61 3D + short_addr $CLOSE ; 62 3E + short_addr $READ ; 63 3F + short_addr $WRITE ; 64 40 + short_addr $UNLINK ; 65 41 + short_addr $LSEEK ; 66 42 + short_addr $CHMOD ; 67 43 + short_addr $IOCTL ; 68 44 + short_addr $DUP ; 69 45 + short_addr $DUP2 ; 70 46 + short_addr $CURRENT_DIR ; 71 47 +; Memory Group + short_addr $ALLOC ; 72 48 + short_addr $DEALLOC ; 73 49 + short_addr $SETBLOCK ; 74 4A +; Process Group + short_addr $EXEC ; 75 4B + short_addr $EXIT ; 76 4C + short_addr $WAIT ; 77 4D + short_addr $FIND_FIRST ; 78 4E +; Special Group + short_addr $FIND_NEXT ; 79 4F +; SPECIAL SYSTEM GROUP +;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; +; C A V E A T P R O G R A M M E R ; +; ; + short_addr $SET_CURRENT_PDB ; 80 50 + short_addr $GET_CURRENT_PDB ; 81 51 + short_addr $GET_IN_VARS ; 82 52 + short_addr $SETDPB ; 83 53 +; ; +; C A V E A T P R O G R A M M E R ; +;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; + short_addr $GET_VERIFY_ON_WRITE ; 84 54 +;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; +; C A V E A T P R O G R A M M E R ; +; ; + short_addr $DUP_PDB ; 85 55 +; ; +; C A V E A T P R O G R A M M E R ; +;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; + short_addr $RENAME ; 86 56 + short_addr $FILE_TIMES ; 87 57 + short_addr $AllocOper ; 88 58 +; Network extention system calls + short_addr $GetExtendedError ; 89 59 + short_addr $CreateTempFile ; 90 5A + short_addr $CreateNewFile ; 91 5B + short_addr $LockOper ; 92 5C + short_addr $ServerCall ; 93 5D + short_addr $UserOper ; 94 5E + short_addr $AssignOper ; 95 5F + short_addr $NameTrans ; 96 60 + short_addr CPMFunc ; 97 61 + short_addr $Get_Current_PDB ; 98 62 +; the next call is reserved for hangool sys call + short_addr $ECS_Call ; 99 63 +;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; +; C A V E A T P R O G R A M M E R ; +; ; + short_addr $Set_Printer_Flag ; 100 64 +; ; +; C A V E A T P R O G R A M M E R ; +;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; + short_addr $GetExtCntry ; 101 65 + short_addr $GetSetCdPg ; 102 66 + short_addr $ExtHandle ; 103 67 + short_addr $Commit ; 104 68 + short_addr $GSetMediaID ; 105 69 ;AN000; + short_addr $Commit ; 106 6A ;AN000; + short_addr $IFS_IOCTL ; 107 6B ;AN000; + short_addr $Extended_Open ; 108 6C ;AN000; +; +VAL2 = ($-DISPATCH)/2 - 1 + + + If Installed + +PUBLIC FOO +FOO LABEL WORD + Short_addr Leave2F +DTab DW OFFSET DOSGroup:DOSTable + PUBLIC FOO,DTAB + +DOSTable LABEL WORD + DB (DOSTableEnd-DOSTable-1)/2 + Short_addr DOSInstall ; 0 install check + Short_addr DOS_CLOSE ; 1 DOS_CLOSE + Short_addr RECSET ; 2 RECSET + Short_addr DOSGetGroup ; 3 Get DOSGROUP + Short_addr PATHCHRCMP ; 4 PATHCHRCMP + Short_addr OUTT ; 5 OUT + Short_addr NET_I24_ENTRY ; 6 NET_I24_ENTRY + Short_addr PLACEBUF ; 7 PLACEBUF + Short_addr FREE_SFT ; 8 FREE_SFT + Short_addr BUFWRITE ; 9 BUFWRITE + Short_addr SHARE_VIOLATION ; 10 SHARE_VIOLATION + Short_addr SHARE_ERROR ; 11 SHARE_ERROR + Short_addr SET_SFT_MODE ; 12 SET_SFT_MODE + Short_addr DATE16 ; 13 DATE16 + Short_addr idle ; 14 empty slot + Short_addr SCANPLACE ; 15 SCANPLACE + Short_addr idle ; 16 empty slot + Short_addr StrCpy ; 17 StrCpy + Short_addr StrLen ; 18 StrLen + Short_addr Ucase ; 19 Ucase + Short_addr POINTCOMP ; 20 POINTCOMP + Short_addr CHECKFLUSH ; 21 CHECKFLUSH + Short_addr SFFromSFN ; 22 SFFromSFN + Short_addr GetCDSFromDrv ; 23 GetCDSFromDrv + Short_addr Get_User_Stack ; 24 Get_User_Stack + Short_addr GetThisDrv ; 25 GetThisDrv + Short_addr DriveFromText ; 26 DriveFromText + Short_addr SETYEAR ; 27 SETYEAR + Short_addr DSUM ; 28 DSUM + Short_addr DSLIDE ; 29 DSLIDE + Short_addr StrCmp ; 30 StrCmp + Short_addr InitCDS ; 31 initcds + Short_addr pJFNFromHandle ; 32 pJfnFromHandle + Short_addr $NameTrans ; 33 $NameTrans + Short_addr CAL_LK ; 34 CAL_LK + Short_addr DEVNAME ; 35 DEVNAME + Short_addr Idle ; 36 Idle + Short_addr DStrLen ; 37 DStrLen + Short_addr NLS_OPEN ; 38 NLS_OPEN DOS 3.3 + Short_addr $CLOSE ; 39 $CLOSE DOS 3.3 + Short_addr NLS_LSEEK ; 40 NLS_LSEEK DOS 3.3 + Short_addr $READ ; 41 $READ DOS 3.3 + Short_addr FastInit ; 42 FastInit DOS 3.4 ;AN000; + Short_addr NLS_IOCTL ; 43 NLS_IOCTL DOS 3.3 + Short_addr GetDevList ; 44 GetDevList DOS 3.3 + Short_addr NLS_GETEXT ; 45 NLS_GETEXT DOS 3.3 + Short_addr MSG_RETRIEVAL ; 46 MSG_RETRIEVAL DOS 4.0 ;AN000; + Short_addr Fake_Version ; 47 Fake_Version DOS 4.0 ;AN006; + +DOSTableEnd LABEL BYTE + + ENDIF + +; NOTE WARNING: This declaration of HEADER must be THE LAST thing in this +; module. The reason is so that the data alignments are the same in +; IBM-DOS and MS-DOS up through header. +;---------------------------------------Start of Korean support 2/11/KK +; +; The varialbes for ECS version are moved here for the same data alignments +; as IBM-DOS and MS-DOS. +; + + I_AM InterChar, byte ; Interim character flag ( 1= interim) ;AN000; + ;AN000; +;------- NOTE: NEXT TWO BYTES SOMETIMES USED AS A WORD !! --------------------- +DUMMY LABEL WORD ;AN000; + PUBLIC InterCon ; Console in Interim mode ( 1= interim) ;AN000; +InterCon db 0 ;AN000; + PUBLIC SaveCurFlg ; Print, do not advance cursor flag ;AN000; +SaveCurFlg db 0 ;AN000; +;-----------------------------------------End of Korean support 2/11/KK + + + PUBLIC HEADER +Header LABEL BYTE + IF DEBUG + DB 13,10,"Debugging DOS version " + DB MAJOR_VERSION + "0" + DB "." + DB (MINOR_VERSION / 10) + "0" + DB (MINOR_VERSION MOD 10) + "0" + ENDIF + + IF NOT IBM + DB 13,10,"MS-DOS version " + DB MAJOR_VERSION + "0" + DB "." + DB (MINOR_VERSION / 10) + "0" + DB (MINOR_VERSION MOD 10) + "0" + + IF HIGHMEM + DB "H" + ENDIF + + DB 13,10, "Copyright 1981,82,83,84,88 Microsoft Corp.",13,10,"$" + ENDIF + +IF DEBUG + DB 13,10,"$" +ENDIF + +MSTAB001E label byte + +include copyrigh.inc ;AN000; + +; SYS init extended table, DOS 3.3 F.C. 5/29/86 +; + PUBLIC SysInitTable + I_need COUNTRY_CDPG,BYTE + I_need SYSINITVAR,BYTE + +SysInitTable label byte + dw OFFSET DOSGROUP:SYSINITVAR ; pointer to sysinit var + dw 0 ; segment + dw OFFSET DOSGROUP:COUNTRY_CDPG ; pointer to country table + dw 0 ; segment of pointer +; DOS 3.3 F.C. 6/12/86 + +; FASTOPEN communications area DOS 3.3 F.C. 5/29/86 +; + PUBLIC FastOpenTable + PUBLIC FastTable ; a better name + EXTRN FastRet:FAR ; defined in misc2.asm + +FastTable label byte ; a better name +FastOpenTable label byte + dw 2 ; number of entries + dw OFFSET DOSGROUP:FastRet ; pointer to ret instr. + dw 0 ; and will be modified by + dw OFFSET DOSGROUP:FastRet ; FASTxxx when loaded in + dw 0 ; +; DOS 3.3 F.C. 6/12/86 + PUBLIC FastFlg ;AN000; flags +FastFlg label byte ;AN000; don't change the following order + I_am FastOpenFlg,BYTE,<0> ;AN000; + I_am FastSeekFlg,BYTE,<0> ;AN000; + + PUBLIC FastOpen_Ext_Info + +; FastOpen_Ext_Info is used as a temporary storage for saving dirpos,dirsec +; and clusnum which are filled by DOS 3.3 when calling FastOpen Insert +; or filled by FastOPen when calling FastOpen Lookup + +FastOpen_Ext_Info label byte + db SIZE FASTOPEN_EXTENDED_INFO dup(0) ;dirpos + +; Dir_Info_Buff is a dir entry buffer which is filled by FastOPen +; when calling FastOpen Lookup + + PUBLIC Dir_Info_Buff + +Dir_Info_Buff label byte + db SIZE dir_entry dup (0) + + + I_am Next_Element_Start,WORD ; save next element start offset + +; Following 4 variables moved to MSDATA.asm (P4986) +; I_am FSeek_drive,BYTE ;AN000; fastseek drive # +; I_am FSeek_firclus,WORD ;AN000; fastseek first cluster # +; I_am FSeek_logclus,WORD ;AN000; fastseek logical cluster # +; I_am FSeek_logsave,WORD ;AN000; fastseek returned log clus # + +; The following is a stack and its pointer for interrupt 2F which is uesd +; by NLSFUNC. There is no significant use of this stack, we are just trying +; not to destroy the INT 21 stack saved for the user. + + + PUBLIC User_SP_2F + +USER_SP_2F LABEL WORD + dw OFFSET DOSGROUP:FAKE_STACK_2F + + PUBLIC Packet_Temp +Packet_Temp label word ; temporary packet used by readtime + PUBLIC DOS_TEMP ; temporary word +DOS_TEMP label word +FAKE_STACK_2F dw 14 dup (0) ; 12 register temporary storage + + PUBLIC Hash_Temp ;AN000; temporary word +Hash_Temp label word ;AN000; + dw 4 dup (0) ;AN000; temporary hash table during config.sys + + PUBLIC SCAN_FLAG ; flag to indicate key ALT_Q +SCAN_FLAG label byte + db 0 +;;; The following 2 words must be adjacent for IBMDOS reasons + + PUBLIC DATE_FLAG +DATE_FLAG label word ; flag to + dw 0 ; to update the date +;;;; special tag for IBMDOS + PUBLIC FETCHI_TAG +FETCHI_TAG label word ; TAG to make DOS 3.3 work + dw 0 ; must be 22642 +;;; The above 2 words must be adjacent for IBMDOS reasons +; DOS 3.3 F.C. 6/12/86 + I_am Del_ExtCluster,WORD ; for dos_delete ;AN000; + + PUBLIC MSG_EXTERROR ; for system message addr ;AN000; +MSG_EXTERROR label DWORD ;AN000; + dd 0 ; for extended error ;AN000; + dd 0 ; for parser ;AN000; + dd 0 ; for critical errror ;AN000; + dd 0 ; for IFS ;AN000; + dd 0 ; for code reduction ;AN000; + + PUBLIC SEQ_SECTOR ; last sector read ;AN000; +SEQ_SECTOR label DWORD ;AN000; + dd -1 ;AN000; + + I_am XA_CONDITION,BYTE,<0> ; for Extended Attributes ;AN000; +; I_am XA_ES,WORD ; for extended find ;AN000; +; I_am XA_BP,WORD ; for extended find ;AN000; +; I_am XA_handle,WORD ; for get/set EA ;AN000; + I_am XA_type,BYTE ; for get/set EA ;AN000; +; I_am XA_device,BYTE ; for get/set EA ;AN000; + I_am XA_from,BYTE ; for get/set EA ;AN000; +; I_am XA_VAR,WORD ; for get/set EA ;AN000; +; I_am XA_TEMP,WORD ; for get/set EA ;AN000; +; I_am XA_TEMP2,WORD ; for get/set EA ;AN000; +; + +; I_am MAX_EA_SIZE,WORD,<29> ; max EA list size ;AN000; +; I_am MAX_EANAME_SIZE,WORD,<20> ; max EA name list size ;AN000; +; I_am XA_COUNT,WORD,<2> ; number of EA entries ;AN000; + + +; PUBLIC XA_TABLE ; for get/set EA ;AN000; +; +;XA_TABLE label byte ;AN000; +; db EAISBINARY ;Code Page ;AN000; +; dw EASYSTEM ;AN000; +; db 0,2 ;AN000; +; dw 2 ;AN000; +; db 'CP' ;AN000; +; +; db EAISBINARY ;File Type ;AN000; +; dw EASYSTEM ;AN000; +; db 0,8 ;AN000; +; dw 1 ;AN000; +; db 'FILETYPE' ;AN000; +; + +; PUBLIC XA_PACKET ;AN000; +;XA_PACKET label byte ;AN000; +;IF DBCS ;AN000; +; dw 18 ;AN000; +; db 18 dup(0) ;AN000; +; PUBLIC DBCS_PACKET ;AN000; +;DBCS_PACKET label byte ;AN000; +; db 5 dup(0) +;ELSE +; dw 2, 0 ; get/set device code page ;AN000; +;ENDIF + I_am CurHashEntry,DWORD ; current hash buffer entry ;AN000; +;; I_am ACT_PAGE,WORD,<-1> ;BL ; active EMS page ;AN000; + I_am SC_SECTOR_SIZE,WORD ; sector size for SC ;AN000; + I_am SC_DRIVE,BYTE ; drive # for secondary cache ;AN000; + I_am CurSC_DRIVE,BYTE,<-1> ; current SC drive ;AN000; + I_am CurSC_SECTOR,DWORD ; current SC starting sector ;AN000; + I_am SC_STATUS,WORD,<0> ; SC status word ;AN000; + I_am SC_FLAG,BYTE,<0> ; SC flag ;AN000; + I_am IFS_DRIVER_ERR,WORD,<0> ; driver error for IFS ;AN000; + + PUBLIC NO_NAME_ID ;AN000; +NO_NAME_ID label byte ;AN000; + db 'NO NAME ' ; null media id ;AN000; + + PUBLIC SWAP_AREA_TABLE ;AN000; +SWAP_AREA_TABLE label byte ;AN000; + I_am NUM_SWAP_AREA,WORD,<2> ; number of swap areas ;AN000; + I_am SWAP_IN_DOS,DWORD ; swap in dos area ;AN000; + I_am SWAP_IN_DOS_LEN,WORD ; swap in dos area length ;AN000; + I_am SWAP_ALWAYS_AREA,DWORD ; swap always area ;AN000; + I_am SWAP_ALWAYS_AREA_LEN,WORD ; swap always area length ;AN000; + I_am IFSFUNC_SWAP_IN_DOS,DWORD ; ifsfunc swap in dos area ;AN000; + I_am IFSFUNC_SWAP_IN_DOS_LEN,WORD ; ifsfunc swap in dos area length ;AN000; + + I_am SWAP_AREA_LEN,WORD ; swap area length ;AN000; + I_am FIRST_BUFF_ADDR,WORD ; first buffer address ;AN000; + I_am SPECIAL_VERSION,WORD,<0> ;AN006; used by INT 2F 47H + I_am FAKE_COUNT,<255> ;AN008; fake version count + I_am OLD_FIRSTCLUS,WORD ;AN011; save old first cluster for fastopen + +TABLE ENDS + + + \ No newline at end of file diff --git a/v4.0/src/DOS/NSTDOS.ASM b/v4.0/src/DOS/NSTDOS.ASM new file mode 100644 index 0000000..f35055f --- /dev/null +++ b/v4.0/src/DOS/NSTDOS.ASM @@ -0,0 +1,7 @@ +; SCCSID = @(#)nstdos.asm 1.1 85/04/10 +TITLE MS-DOS +NAME MSDOS_3 + +include stdsw.asm +include msconst.asm + END diff --git a/v4.0/src/DOS/OPEN.ASM b/v4.0/src/DOS/OPEN.ASM new file mode 100644 index 0000000..ab9b4c1 --- /dev/null +++ b/v4.0/src/DOS/OPEN.ASM @@ -0,0 +1,569 @@ +; SCCSID = @(#)open.asm 1.1 85/04/10 +TITLE DOS_OPEN - Internal OPEN call for MS-DOS +NAME DOS_OPEN +; Low level routines for openning a file from a file spec. +; Also misc routines for sharing errors +; +; DOS_Open +; Check_Access_AX +; SHARE_ERROR +; SET_SFT_MODE +; Code_Page_Mismatched_Error ; DOS 4.00 +; +; Revision history: +; +; Created: ARR 30 March 1983 +; A000 version 4.00 Jan. 1988 +; + +; +; get the appropriate segment definitions +; +.xlist +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +include dossym.inc +include devsym.inc +include fastopen.inc +include fastxxxx.inc ;AN000; +include ifssym.inc ;AN000; +.cref +.list + +Installed = TRUE + + i_need NoSetDir,BYTE + i_need THISSFT,DWORD + i_need THISCDS,DWORD + i_need CURBUF,DWORD + i_need CurrentPDB,WORD + i_need CURR_DIR_END,WORD + I_need RetryCount,WORD + I_need Open_Access,BYTE + I_need fSharing,BYTE + i_need JShare,DWORD + I_need FastOpenFlg,byte + I_need EXTOPEN_ON,BYTE ;AN000;; DOS 4.00 + I_need ALLOWED,BYTE ;AN000;; DOS 4.00 + I_need EXTERR,WORD ;AN000;; DOS 4.00 + I_need EXTERR_LOCUS,BYTE ;AN000;; DOS 4.00 + I_need EXTERR_ACTION,BYTE ;AN000;; DOS 4.00 + I_need EXTERR_CLASS,BYTE ;AN000;; DOS 4.00 + I_need CPSWFLAG,BYTE ;AN000;; DOS 4.00 + I_need EXITHOLD,DWORD ;AN000;; DOS 4.00 + I_need THISDPB,DWORD ;AN000;; DOS 4.00 + I_need SAVE_CX,WORD ;AN000;; DOS 4.00 + +Break + +; Inputs: +; [WFP_START] Points to WFP string ("d:/" must be first 3 chars, NUL +; terminated) +; [CURR_DIR_END] Points to end of Current dir part of string +; ( = -1 if current dir not involved, else +; Points to first char after last "/" of current dir part) +; [THISCDS] Points to CDS being used +; (Low word = -1 if NUL CDS (Net direct request)) +; [THISSFT] Points to SFT to fill in if file found +; (sf_mode field set so that FCB may be detected) +; [SATTRIB] Is attribute of search, determines what files can be found +; AX is Access and Sharing mode +; High NIBBLE of AL (Sharing Mode) +; sharing_compat file is opened in compatibility mode +; sharing_deny_none file is opened Multi reader, Multi writer +; sharing_deny_read file is opened Only reader, Multi writer +; sharing_deny_write file is opened Multi reader, Only writer +; sharing_deny_both file is opened Only reader, Only writer +; Low NIBBLE of AL (Access Mode) +; open_for_read file is opened for reading +; open_for_write file is opened for writing +; open_for_both file is opened for both reading and writing. +; +; For FCB SFTs AL should = sharing_compat + open_for_both +; (not checked) +; Function: +; Try to open the specified file +; Outputs: +; sf_ref_count is NOT altered +; CARRY CLEAR +; THISSFT filled in. +; CARRY SET +; AX is error code +; error_file_not_found +; Last element of path not found +; error_path_not_found +; Bad path (not in curr dir part if present) +; error_bad_curr_dir +; Bad path in current directory part of path +; error_invalid_access +; Bad sharing mode or bad access mode or bad combination +; error_access_denied +; Attempt to open read only file for writting, or +; open a directory +; error_sharing_violation +; The sharing mode was correct but not allowed +; generates an INT 24 on compatibility mode SFTs +; DS preserved, others destroyed + + procedure DOS_Open,NEAR + DOSAssume CS,,"DOS_Open" + ASSUME ES:NOTHING + + MOV [NoSetDir],0 + CALL Check_Access_AX + retc + LES DI,[THISSFT] + XOR AH,AH +; sleaze! move only access/sharing mode in. Leave sf_isFCB unchanged + MOV BYTE PTR ES:[DI.sf_mode],AL ; For moment do this on FCBs too + PUSH ES + LES SI,[THISCDS] + CMP SI,-1 + JNZ TEST_RE_NET + POP ES +;Extended open hooks + + TEST [EXTOPEN_ON],ext_open_on ;FT. from extnded open ;AN000; + JZ NOEXTOP ;FT. no, do normal ;AN000; +IFS_extopen: ;AN000; + MOV AL,byte ptr [SAVE_CX] ;FT. al= create attribute ;AN000; + PUSH AX ;FT. pass create attr to IFS ;AN000; + MOV AX,(multNET SHL 8) OR 46 ;FT. issue extended open verb ;AN000; + INT 2FH ;FT. ;AN000; + POP BX ;FT. trash bx ;AN000; + MOV [EXTOPEN_ON],0 ;FT. ;AN000; + JNC update_size ;IFS. file may be opened ;AN000; + return ;FT. ;AN000; +NOEXTOP: +;Extended open hooks + + +IF NOT Installed + transfer NET_SEQ_OPEN +ELSE + PUSH AX + MOV AX,(multNET SHL 8) OR 22 + INT 2FH + POP BX ; clean stack + return +ENDIF + +TEST_RE_NET: + TEST ES:[SI.curdir_flags],curdir_isnet + POP ES + JZ LOCAL_OPEN +; CALL IFS_SHARE_CHECK ;IFS. check IFS share,may create share ;AN000; +; JC nomore ;IFS. share violation ;AN000; +;Extended open hooks + + TEST [EXTOPEN_ON],ext_open_on ;FT. from extnded open ;AN000; + JNZ IFS_extopen ;FT. isuue extended open ;AN000; +;Extended open hooks + +IF NOT Installed + transfer NET_OPEN +ELSE + PUSH AX + MOV AX,(multNET SHL 8) OR 22 + INT 2FH + POP BX ; clean stack +; JC nomore ;IFS. error ;AN000; +update_size: ;AN000; +; CALL OWN_SHARE ;IFS. IFS owns share ? ;AN000; +; JZ nomore2 ;IFS. yes ;AN000; +; MOV AX,3 ;IFS. update file size for all SFT ;AN000; +; LES DI,ThisSFT ;IFS. ;AN000; +; call JShare + 14 * 4 ;IFS. call ShSu ;AN000; +nomore2: +; CLC +nomore: + return +ENDIF + +LOCAL_OPEN: + EnterCrit critDisk + +; DOS 3.3 FastOPen 6/16/86 + + OR [FastOpenFlg],FastOpen_Set+Special_Fill_Set ; only open can + invoke GetPath + + +; DOS 3.3 FastOPen 6/16/86 + + JNC Open_found + JNZ bad_path + OR CL,CL + JZ bad_path +OpenFNF: + MOV AX,error_file_not_found +OpenBadRet: + AND BYTE PTR CS:[FastOpenFlg],Fast_yes ;; DOS 3.3 + STC + LeaveCrit critDisk + JMP Clear_FastOpen + +bad_path: + MOV AX,error_path_not_found + JMP OpenBadRet + +open_bad_access: + MOV AX,error_access_denied + JMP OpenBadRet + +Open_found: + JZ Open_Bad_Access ; test for directories + OR AH,AH + JS open_ok ; Devices don't have attributes + MOV ES,WORD PTR [CURBUF+2] ; get buffer location + MOV AL,ES:[BX].dir_attr + TEST AL,attr_volume_id ; can't open volume ids + JNZ open_bad_access + TEST AL,attr_read_only ; check write on read only + JZ open_ok +; +; The file is marked READ-ONLY. We verify that the open mode allows access to +; the read-only file. Unfortunately, with FCB's and net-FCB's we cannot +; determine at the OPEN time if such access is allowed. Thus, we defer such +; processing until the actual write operation: +; +; If FCB, then we change the mode to be read_only. +; If net_FCB, then we change the mode to be read_only. +; If not open for read then error. +; + SaveReg + LDS SI,[THISSFT] + MOV CX,[SI].sf_mode + TEST CX,sf_isFCB ; is it FCB? + JNZ ResetAccess ; yes, reset the access + MOV DL,CL + AND DL,sharing_mask + CMP DL,sharing_net_FCB ; is it net FCB? + JNZ NormalOpen ; no +ResetAccess: + AND CX,NOT access_mask ; clear access + errnz open_for_read +; OR CX,open_for_read ; stick in open_for_read + MOV [SI].sf_mode,CX + JMP SHORT FillSFT +; +; The SFT is normal. See if the requested access is open_for_read +; +NormalOpen: + AND CL,access_mask ; remove extras + CMP CL,open_for_read ; is it open for read? + JZ FillSFT + RestoreReg + JMP short open_bad_access +; +; All done, restore registers and fill the SFT. +; +FillSFT: + RestoreReg +open_ok: +;;; File Tagging DOS 4.00 +; OR AH,AH ;FT. device ? ;AN000; +; JS NORM0 ;FT. yes, don't do code page matching ;AN000; +; CMP [CPSWFLAG],0 ;FT. code page matching on ;AN000; +; JZ NORM0 ;FT. no ;AN000; +; CMP ES:[BX].dir_CODEPG,0 ;FT. code page 0 ;AN000; +; JZ NORM0 ;FT. yes do nothing ;AN000; +; PUSH AX ;FT. ;AN000; +; invoke Get_Global_CdPg ;FT. get global code page ;AN000; +; CMP ES:[BX].dir_CODEPG,AX ;FT. equal to global code page ;AN000; +; JZ NORM1 ;FT. yes ;AN000; +; call Code_Page_Mismatched_Error ;FT. ;AN000; +; CMP AL,0 ;FT. ignore ? ;AN000; +; JZ NORM1 ;FT. ;AN000; +; POP AX ;FT. ;AN000; +; JMP open_bad_access ;FT. set carry and return ;AN000; +NORM1: ;AN000; +; POP AX ;FT. ;AN000; +NORM0: + +;;; File Tagging DOS 4.00 + invoke DOOPEN ; Fill in SFT + AND BYTE PTR CS:[FastOpenFlg],Fast_yes ;; DOS 3.3 + CALL DO_SHARE_CHECK ; + JNC Share_Ok + LeaveCrit critDisk + JMP Clear_FastOPen + +SHARE_OK: + MOV AX,3 + LES DI,ThisSFT +if installed + call JShare + 14 * 4 +else + Call ShSU +endif +;; DOS 4.00 10/27/86 + LES DI,ThisSFT ; if this is a newly ;AN000; + CMP ES:[DI.sf_firclus],0 ; created file then ;AN000; + JZ no_fastseek ; do nothing ;AN000; + MOV CX,ES:[DI.sf_firclus] ; first cluster # ;AN000; + LES DI,ES:[DI.sf_devptr] ; pointer to DPB ;AN000; + MOV DL,ES:[DI.dpb_drive] ; drive # ;AN000; + invoke FastSeek_Open ; call fastseek ;AN000; +no_fastseek: + +;; DOS 4.00 10/27/86 + + LeaveCrit critDisk + +; +; Finish SFT initialization for new reference. Set the correct mode. +; +; Inputs: +; ThisSFT points to SFT +; +; Outputs: +; Carry clear +; Registers modified: AX. + + entry SET_SFT_MODE + DOSAssume CS,,"Set_SFT_Mode" + ASSUME ES:NOTHING + + LES DI,ThisSFT + invoke DEV_OPEN_SFT + TEST ES:[DI.sf_mode],sf_isfcb; Clears carry + retz ; sf_mode correct + MOV AX,[CurrentPDB] + MOV ES:[DI.sf_PID],AX ; For FCB sf_PID=PID + +Clear_FastOpen: + return ;;;;; DOS 3.3 + +EndProc DOS_Open + +; Called on sharing violations. ES:DI points to SFT. AX has error code +; If SFT is FCB or compatibility mode gens INT 24 error. +; Returns carry set AX=error_sharing_violation if user says ignore (can't +; really ignore). Carry clear +; if user wants a retry. ES, DI, DS preserved + +procedure SHARE_ERROR,NEAR + DOSAssume CS,,"Share_Error" + ASSUME ES:NOTHING + TEST ES:[DI.sf_mode],sf_isfcb + JNZ HARD_ERR + MOV CL,BYTE PTR ES:[DI.sf_mode] + AND CL,sharing_mask + CMP CL,sharing_compat + JNE NO_HARD_ERR +HARD_ERR: + invoke SHARE_VIOLATION + retnc ; User wants retry +NO_HARD_ERR: + MOV AX,error_sharing_violation + STC + return + +EndProc SHARE_ERROR + + +; Input: THISDPB, WFP_Start, THISSFT set +; Functions: check file sharing mode is valid +; Output: carry set, error +; carry clear, share ok + +procedure DO_SHARE_CHECK,NEAR + DOSAssume CS,,"DO_SHARE__CHECK" + ASSUME ES:NOTHING + EnterCrit critDisk ; enter critical section + +OPN_RETRY: + MOV CX,RetryCount ; Get # tries to do +OpenShareRetry: + SaveReg ; Save number left to do + invoke SHARE_CHECK ; Final Check + RestoreReg ; CX = # left + JNC Share_Ok2 ; No problem with access + Invoke Idle + LOOP OpenShareRetry ; One more retry used up +OpenShareFail: + LES DI,[ThisSft] + invoke SHARE_ERROR + JNC OPN_RETRY ; User wants more retry +Share_Ok2: + LeaveCrit critDisk ; leave critical section + return + +EndProc DO_SHARE_CHECK + + +; Input: ES:DI -> SFT +; Functions: check if IFS owns SHARE +; Output: Zero set, use IFS SHARE +; otherwise, use DOS SHARE + +procedure OWN_SHARE,NEAR ;AN000; + DOSAssume CS,,"OWN_SHARE" ;AN000; + ASSUME ES:NOTHING ;AN000; + +; PUSH DS ;IFS. save reg ;AN000; +; PUSH SI ;IFS. save reg ;AN000; +; LDS SI,ES:[DI.sf_IFS_HDR] ;IFS. ds:si-> IFS header ;AN000; +; TEST [SI.IFS_ATTRIBUTE],IFSUSESHARE ;IFS. save reg ;AN000; +; POP SI ;IFS. retore reg ;AN000; +; POP DS ;IFS. restore reg ;AN000; + return ;IFS. return ;AN000; + +EndProc OWN_SHARE ;AN000; + + +; Input: THISCDS -> CDS +; Functions: check if IFS owns SHARE +; Output: Zero set, use IFS SHARE +; otherwise, use DOS SHARE + +procedure OWN_SHARE2,NEAR ;AN000; + DOSAssume CS,,"OWN_SHARE2" ;AN000; + ASSUME ES:NOTHING ;AN000; + +; CMP WORD PTR [THISCDS],-1 ;IFS. UNC ? ;AN000; +; JZ ifs_hasit ;IFS. yes ;AN000; +; PUSH DS ;IFS. save reg ;AN000; +; PUSH SI ;IFS. save reg ;AN000; +; LDS SI,[THISCDS] ;IFS. DS:SI -> ThisCDS ;AN000; +; LDS SI,[SI.curdir_IFS_HDR] ;IFS. ds:si-> IFS header ;AN000; +; TEST [SI.IFS_ATTRIBUTE],IFSUSESHARE ;IFS. ;AN000; +; POP SI ;IFS. retore reg ;AN000; +; POP DS ;IFS. restore reg ;AN000; +ifs_hasit: ;AN000; + return ;IFS. return ;AN000; + +EndProc OWN_SHARE2 ;AN000; + + +; Input: ES:DI -> SFT +; Functions: set THISDPB +; Output: none + +procedure SET_THISDPB,NEAR ;AN000; + DOSAssume CS,,"SET_THISDPB" ;AN000; + ASSUME ES:NOTHING ;AN000; + +; PUSH DS ;IFS. save reg ;AN000; +; PUSH SI ;IFS. save reg ;AN000; +; LDS SI,[THISCDS] ;IFS. ds:si-> CDS ;AN000; +; LDS SI,[SI.CURDIR_DEVPTR] ;IFS. ds:si-> DPB ;AN000; +; MOV WORD PTR [THISDPB],SI ;IFS. set THISDPB ;AN000; +; MOV WORD PTR [THISDPB+2],DS ;IFS. ;AN000; +; POP SI ;IFS. retore reg ;AN000; +; POP DS ;IFS. restore reg ;AN000; + return ;IFS. return ;AN000; + +EndProc SET_THISDPB ;AN000; + + +; Input: ES:DI -> SFT +; Functions: check IFS share +; Output: none + +procedure IFS_SHARE_CHECK,NEAR ;AN000; + DOSAssume CS,,"IFS_SHARE_CHECK" ;AN000; + ASSUME ES:NOTHING ;AN000; + + +; CALL OWN_SHARE ;IFS. IFS owns share ;AN000; +; JZ IFSSHARE ;IFS. yes ;AN000; +; PUSH AX ;IFS. save mode ;AN000; +; CALL SET_THISDPB ;IFS. set THISDPB for SHARE_VIOLATION ;AN000; +; CALL DO_SHARE_CHECK ;IFS. check share ;AN000; +; POP AX ;IFS. restore mode and share ok ;AN000; +IFSSHARE: ;AN000; + return ;IFS. return ;AN000; + +EndProc IFS_SHARE_CHECK ;AN000; + +; Inputs: +; AX is mode +; High NIBBLE of AL (Sharing Mode) +; sharing_compat file is opened in compatibility mode +; sharing_deny_none file is opened Multi reader, Multi writer +; sharing_deny_read file is opened Only reader, Multi writer +; sharing_deny_write file is opened Multi reader, Only writer +; sharing_deny_both file is opened Only reader, Only writer +; Low NIBBLE of AL (Access Mode) +; open_for_read file is opened for reading +; open_for_write file is opened for writing +; open_for_both file is opened for both reading and writing. +; Function: +; Check this access mode for correctness +; Outputs: +; [open_access] = AL input +; Carry Clear +; Mode is correct +; AX unchanged +; Carry Set +; Mode is bad +; AX = error_invalid_access +; No other registers effected + + procedure Check_Access_AX + DOSAssume CS,,"Check_Access" + ASSUME ES:NOTHING + + MOV Open_Access,AL + PUSH BX +; +; If sharing, then test for special sharing mode for FCBs +; + MOV BL,AL + AND BL,sharing_mask + CMP fSharing,-1 + JNZ CheckShareMode ; not through server call, must be ok + CMP BL,sharing_NET_FCB + JZ CheckAccessMode ; yes, we have an FCB +CheckShareMode: + CMP BL,40h ; is this a good sharing mode? + JA Make_Bad_Access +CheckAccessMode: + MOV BL,AL + AND BL,access_mask + CMP BL,2 + JA Make_Bad_Access + POP BX + CLC + return + +make_bad_access: + MOV AX,error_invalid_access + POP BX + STC + return + +EndProc Check_Access_AX + +; Input: none +; Function: Issue Code Page Mismatched INT 24 Critical Error +; OutPut: AL =0 ignore +; =3 fail + +procedure Code_Page_Mismatched_Error,NEAR ;AN000; + DOSAssume CS,,"Code_Page_Mismatched_Error" ;AN000; + ASSUME ES:NOTHING ;AN000; + +; PUSH DS ;FT. ;AN000; +; Context DS ;FT. ds=cs ;AN000; +; MOV AH,0A9H ;FT. fail,ignore,device,write ;AN000; +; MOV DI,error_I24_gen_failure ;FT. set error ;AN000; +; MOV [EXTERR],error_Code_Page_Mismatched ;FT. ;AN000; +; MOV [EXTERR_CLASS],errCLASS_NotFnd ;FT. ;AN000; +; MOV [EXTERR_ACTION],errACT_Abort ;FT. ;AN000; +; MOV [EXTERR_LOCUS],errLOC_Unk ;FT. ;AN000; +; MOV word ptr [EXITHOLD + 2],ES ;FT. save es:bp ;AN000; +; MOV word ptr [EXITHOLD],BP ;FT. ;AN000; +; invoke NET_I24_ENTRY ;FT. issue int 24H ;AN000; +; POP DS ;FT. ;AN000; +; return ;FT. ;AN000; + +EndProc Code_Page_Mismatched_Error ;AN000; +CODE ENDS + END diff --git a/v4.0/src/DOS/PARSE.ASM b/v4.0/src/DOS/PARSE.ASM new file mode 100644 index 0000000..f8de345 --- /dev/null +++ b/v4.0/src/DOS/PARSE.ASM @@ -0,0 +1,447 @@ +; SCCSID = @(#)parse.asm 1.2 85/07/23 +TITLE PARSE - Parsing system calls for MS-DOS +NAME PARSE +; +; System calls for parsing command lines +; +; $PARSE_FILE_DESCRIPTOR +; +; Modification history: +; +; Created: ARR 30 March 1983 +; EE PathParse 10 Sept 1983 +; + +.xlist +; +; get the appropriate segment definitions +; +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +.cref +.list + +BOGUS =FALSE +.lall + I_Need chSwitch,BYTE + +BREAK <$Parse_File_Descriptor -- Parse an arbitrary string into an FCB> + +; Inputs: +; DS:SI Points to a command line +; ES:DI Points to an empty FCB +; Bit 0 of AL = 1 At most one leading separator scanned off +; = 0 Parse stops if separator encountered +; Bit 1 of AL = 1 If drive field blank in command line - leave FCB +; = 0 " " " " " " - put 0 in FCB +; Bit 2 of AL = 1 If filename field blank - leave FCB +; = 0 " " " - put blanks in FCB +; Bit 3 of AL = 1 If extension field blank - leave FCB +; = 0 " " " - put blanks in FCB +; Function: +; Parse command line into FCB +; Returns: +; AL = 1 if '*' or '?' in filename or extension, 0 otherwise +; DS:SI points to first character after filename + + procedure $PARSE_FILE_DESCRIPTOR,NEAR +ASSUME DS:NOTHING,ES:NOTHING + + invoke MAKEFCB + PUSH SI + invoke get_user_stack + POP [SI.user_SI] + return +EndProc $PARSE_FILE_DESCRIPTOR + + +IF BOGUS +BREAK <$PathParse - Parse a string> + +;------------------------------------------------------------------------------ +; +; Parse is a string parser. It copies the next token into a buffer, updates +; the string pointer, and builds a flag word which describes the token. +; +; ENTRY +; DS:SI - Points to the beginning of the string to be parsed +; ES:DI - Points to the buffer which will hold the new token +; +; EXIT +; AX - Flag word +; DS:SI - String pointer updated to point past the token just found +; All other registers are unchanged. +; +; All of the isXXXX procedures called by the main routine test a character +; to see if it is of a particular type. If it is, they store the character +; and return with the ZF set. +; +; CALLS +; isswit issep ispchr ispsep isinval isdot ischrnull dirdot pasep +; +; +; INTERNAL REGISTER USAGE +; AH - FF/00 to indicate whether a path token can terminated with a +; slash or not. +; AL - Used with lodsb/stosb to transfer and test chars from DS:SI +; BX - Holds flag word +; CX - Used with loop/rep and as a work var +; DX - Used to test the length of names and extensions +; +; EFFECTS +; The memory pointed to by DI has the next token copied into it. +; +; WARNINGS +; It is the caller's responsibility to make sure DS:SI does not point +; to a null string. If it does, SI is incremented, a null byte is +; stored at ES:DI, and the routine returns. +; +;------------------------------------------------------------------------------ +ParseClassMask equ 1110000000000000b ; Token class mask +ParseSwitch equ 1000000000000000b ; Switch class +ParseSeparators equ 0100000000000000b ; Separator class +ParsePathName equ 0010000000000000b ; Path class +ParsePathNameData equ 0000000000001111b ; Path token data mask +ParsePathSynErr equ 0000000000000001b ; Path has syntax error +ParsePathWild equ 0000000000000010b ; Path has wildcards +ParsePathSeparators equ 0000000000000100b ; Path has pseparators +ParseInvalidDrive equ 0000000000001000b ; Path has invald drive + + +; Sepchars is a string containing all of the token separator characters +; and is used to test for separators. + +Table segment +Public PRS001S,PRS001E +PRS001S label byte +sepchrs db 9,10,13,' ','+',',',';','=' ; tab cr lf sp + , ; = +seplen equ $-sepchrs +PRS001E label byte +table ends + +Procedure $PathParse,NEAR + assume ds:nothing,es:nothing + xor ah,ah ; initialize registers and flags + xor bx,bx + cld + lodsb ; used the first byte of the token to + call isswit ; determine its type and call the routine to + je switch ; parse it + call issep + je separ + call ispchr + je path + call ispsep + je path + call isdot + je path + call isinval + je inval + stosb + jmp done + +inval: or bx,ParsePathName ; an invalid character/path token + or bx,ParsePathSynErr ; was found, set the appropriate + call issep ; flag bits and parse the rest of + jne icont ; the token + dec di +icont: dec si + jmp ptosep + +switch: mov bx,ParseSwitch ; found a switch, set flag and parse + jmp ptosep ; the rest of it + +separ: mov bx,ParseSeparators ; found separator, set flag and parse +seloop: lodsb ; everything up to the next non + call issep ; separator character + je seloop + jmp bksi + +path: or bx,ParsePathName ; found path, set flag + mov cx,8 ; set up to parse a file name + mov dx,8 + call pasep ; if the token began with a path + jne pcont1 ; separator or . call rcont which + not ah ; handles checksfor . and .. + jmp rcont +pcont1: cmp al,'.' + jne pcont2 + dec si + dec di + jmp rcont +pcont2: cmp al,'A' ; if token may start with a drive + jge drive ; designator, go to drive. otherwise + jmp name1 ; parse a file name. + +drive: cmp byte ptr [si],':' ; if there is a drive designator, parse + jne name1 ; and verify it. otherwise parse a file + not ah ; name. + cmp al,'Z' + jle dcont1 + sub al,' ' +dcont1: sub al,'@' + invoke GetthisDrv + lodsb + stosb + jc dcont2 + jmp dcont3 +dcont2: or bx,ParseInvalidDrive +dcont3: dec cx + lodsb + call ispsep + je rcont + dec si + +repeat: mov al,byte ptr [si-2] ; repeat and rcont test for //, \\, ., + call pasep ; and .. and repeatedly calls name + jne rcont ; and ext until a path token has + inc si ; been completely parsed. + jmp inval +rcont: call dirdot + je done + jc inval + mov cx,8 + mov dx,8 + jmp name + +name1: dec cx +name: lodsb ; parse and verify a file name + call ispchr + jne ncheck + xor ah,ah +nloop: loop name + lodsb + +ncheck: cmp ah,0 + jne ncont + cmp cx,dx + jne ncont + jmp inval +ncont: call isdot + je ext + jmp dcheck + +ext: mov cx,3 ; parse and verify a file extension + mov dx,3 +extl: lodsb + call ispchr + jne echeck +eloop: loop extl + lodsb + +echeck: cmp cx,dx + jne dcheck + jmp inval + +dcheck: call ispsep ; do the checks need to make sure + je repeat ; a file name or extension ended + call issep ; correctly and checks to see if + je bkboth ; we're done + call ischrnull + je done + jmp inval + +ptosep: lodsb ; parse everything to the next separator + call issep + je bkboth + call ischrnull + je done + call isinval + jne ptcont + or bx,ParsePathSynErr +ptcont: stosb + jmp ptosep + +bkboth: dec di ; clean up when the end of the token +bksi: dec si ; is found, stick a terminating null +done: xor al,al ; byte at the end of buf, and exit + stosb + push si + invoke Get_user_stack + mov [si].user_AX,bx + pop [si].user_SI + Transfer sys_ret_ok + +Endproc $PathParse + +; Is current character the beginning of a switch? + +isswit proc near + cmp al,[chSwitch] + jne swret + stosb +swret: ret +isswit endp + + +; Is the current character a separator? + +issep proc near + push cx + push di + push es + mov cx,cs + mov es,cx + mov cx,seplen + mov di,offset dosgroup:sepchrs + repne scasb + pop es + pop di + jne sepret +sepyes: stosb +sepret: pop cx + ret +issep endp + + +; Is the current character a path character? If it is a wildcard char too, +; set that flag. + +ispchr proc near + cmp al,'!' + je pcyes + cmp al,'#' + jl pcret + cmp al,'*' + je pcwild + jl pcyes + cmp al,'-' + je pcyes + cmp al,'0' + jl pcret + cmp al,'9' + jle pcyes + cmp al,'?' + je pcwild + jl pcret + cmp al,'Z' + jle pcyes + cmp al,'^' + jl pcret + cmp al,'{' + jle pcyes + cmp al,'}' + je pcyes + cmp al,'~' + je pcyes + jmp pcret +pcwild: or bx,ParsePathWild +pcyes: stosb + cmp al,al +pcret: ret +ispchr endp + + +; Is the current character a path separator? If so, set that flag after +; storing the byte. + +ispsep proc near + call pasep + jne psret + stosb + or bx,ParsePathSeparators + cmp al,al +psret: ret +ispsep endp + + +; Set ZF if the character in AL is a path separator. + +pasep proc near + cmp chSwitch,'/' + je bkslash + cmp al,'/' + retz +bkslash:cmp al,'\' + ret +pasep endp + + +; Is the current character invalid? + +isinval proc near + cmp al,1 + jl inret + cmp al,8 + jle inyes + cmp al,11 + jl inret + cmp al,13 + jne incont + cmp al,0 + ret +incont: cmp al,31 + jle inyes + cmp al,'[' + je inyes + cmp al,']' + je inyes + ret +inyes: cmp al,al +inret: ret +isinval endp + + +; Is the current character a dot? + +isdot proc near + cmp al,'.' + jne dotret + stosb +dotret: ret +isdot endp + + +; Is the current character null? If so, update SI for exiting. + +ischrnull proc near + cmp al,0 + jne nulret + dec si + cmp al,al +nulret: ret +ischrnull endp + + +; Check for . and .. Before returning, CF and ZF are set to indicate whether +; the token is invalid (found . or .. followed by an invalid char - CF on), +; we're done (found . or .. followed by null or a separator - ZF on), or the +; token continues (. and .. not found or found and followed by a path +; separator - both flags off). + +dirdot proc near + cmp byte ptr [si], '.' + jne diretc + lodsb + stosb + cmp byte ptr [si],'.' + jne dicont + lodsb + stosb +dicont: lodsb + call ispsep + je diretc + call issep + je dibk + call ischrnull + je diretd +direti: stc ; Invalid return + ret +dibk: dec si + dec di +diretd: cmp al,al ; Done return + ret +diretc: cmp ah,1 ; Continue return + clc + ret +dirdot endp +ENDIF + +CODE ENDS + END diff --git a/v4.0/src/DOS/PATH.ASM b/v4.0/src/DOS/PATH.ASM new file mode 100644 index 0000000..5deed6c --- /dev/null +++ b/v4.0/src/DOS/PATH.ASM @@ -0,0 +1,363 @@ +; SCCSID = @(#)path.asm 1.1 85/04/10 +TITLE PATH - Directory related system calls +NAME PATH + +; +; Directory related system calls. These will be passed direct text of the +; pathname from the user. They will need to be passed through the macro +; expander prior to being sent through the low-level stuff. I/O specs are +; defined in DISPATCH. The system calls are: +; +; $CURRENT_DIR Written +; $RMDIR Written +; $CHDIR Written +; $MKDIR Written +; +; +; Modification history: +; +; Created: ARR 4 April 1983 +; MZ 10 May 1983 CurrentDir implemented +; MZ 11 May 1983 RmDir, ChDir, MkDir implemented +; EE 19 Oct 1983 RmDir no longer allows you to delete a +; current directory. +; MZ 19 Jan 1983 Brain damaged applications rely on success +; values of AL. +.xlist +; +; get the appropriate segment definitions +; +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGroup,CS:DOSGroup + +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +.cref +.list + + EXTRN DOS_MkDir:NEAR,DOS_RmDir:NEAR + + I_Need ThisCDS,DWORD ; pointer to Current CDS + I_Need WFP_Start,WORD ; pointer to beginning of directory text + I_Need Curr_Dir_End,WORD ; offset to end of directory part + I_Need OpenBuf,128 ; temp spot for translated name + I_need fSplice,BYTE ; TRUE => do splice + I_Need NoSetDir,BYTE ; TRUE => no exact match on splice + I_Need cMeta,BYTE + I_Need DrvErr,BYTE ;AN000; + +BREAK <$CURRENT_DIR - dump the current directory into user space> +; +; Assembler usage: +; LDS SI,area +; MOV DL,drive +; INT 21h +; ; DS:SI is a pointer to 64 byte area that contains drive +; ; current directory. +; Error returns: +; AX = error_invalid_drive +; + + procedure $CURRENT_DIR,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING + EnterCrit critDisk + MOV AL,DL ; get drive number (0=def, 1=A) + Invoke GetVisDrv ; grab it + JNC CurrentValidate ; no error -> go and validate dir +CurdirErr: + LeaveCrit critDisk + MOV AL,[DrvErr] ;IFS. ;AN000; + transfer SYS_RET_ERR ;IFS. make noise ;AN000; +CurrentValidate: + SaveReg ; save destination + LDS SI,ThisCDS + TEST [SI].curdir_flags,curdir_isnet + JNZ DoCheck +; Random optimization nuked due to some utilities using GetCurrentDir to do +; media check. +; CMP [SI].curdir_id,0 +; JZ GetDst +DoCheck: + MOV NoSetDir,0 ; interested only in contents + MOV DI,OFFSET DOSGroup:OpenBuf + Invoke ValidateCDS ; output is ES:DI -> CDS + SaveReg ; swap source and destination + RestoreReg +GetDst: + RestoreReg ; get real destination + JC CurdirErr + ADD SI,curdir_text + ADD SI,[SI.curdir_END] + CMP BYTE PTR [SI],'\' ; root or subdirs present? + JNZ CurrentCopy + INC SI +CurrentCopy: +; Invoke FStrCpy +;; 10/29/86 E5 char + PUSH AX + LODSB ; get char + OR AL,AL + JZ FOK + CMP AL,05 + JZ FCHANGE + JMP FFF +FCPYNEXT: + LODSB ; get char +FFF: + CMP AL,'\' ; beginning of directory + JNZ FOK ; no + STOSB ; put into user's buffer + LODSB ; 1st char of dir is 05? + CMP AL,05H + JNZ FOK ; no +FCHANGE: + MOV AL,0E5H ; make it E5 +FOK: + STOSB ; put into user's buffer + OR AL,AL ; final char + JNZ FCPYNEXT ; no + POP AX + +;; 10/29/86 E5 char + xor AL,AL ; MZ 19 Jan 84 + LeaveCrit critDisk + transfer Sys_Ret_OK ; no more, bye! +EndProc $Current_Dir + +BREAK <$RmDir -- Remove a directory> + +; Inputs: +; DS:DX Points to asciz name +; Function: +; Delete directory if empty +; Returns: +; STD XENIX Return +; AX = error_path_not_found If path bad +; AX = error_access_denied If +; Directory not empty +; Path not directory +; Root directory specified +; Directory malformed (. and .. not first two entries) +; User tries to delete a current directory +; AX = error_current_directory + + procedure $RMDIR,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup + + push dx ; Save ptr to name + push ds + mov si,dx ; Load ptr into si + mov di,offset DOSGroup:OpenBuf ; di = ptr to buf for trans name + push di + Invoke TransPathNoSet ; Translate the name + pop di ; di = ptr to buf for trans name + jnc rmlset ; If transpath succeeded, continue + pop ds + pop dx ; Restore the name + error error_path_not_found ; Otherwise, return an error + +rmlset: + CMP cMeta,-1 ; if (cMeta >= 0) + Jnz rmerr ; return (-1); + Context ES + xor al,al ; al = 0 , ie drive a: +rmloop: Invoke GetCDSFromDrv ; Get curdir for drive in al + jc rmcont ; If error, exit loop & cont normally + Invoke StrCmp ; Are the 2 paths the same? + jz rmerr ; Yes, report error. + inc al ; No, inc al to next drive number + jmp rmloop ; Go check next drive. + +rmerr: + pop ds + pop dx ; Restore the name + error error_current_directory ; error + +rmcont: + pop ds + pop dx ; Restore the name + MOV SI,OFFSET DOSGroup:DOS_RmDIR + JMP DoDirCall +EndProc $RMDIR + +BREAK <$ChDir -- Change current directory on a drive> + +; +; $ChDir - Top-level change directory system call. This call is responsible +; for setting up the CDS for the specified drive appropriately. There are +; several cases to consider: +; +; o Local, simple CDS. In this case, we take the input path and convert +; it into a WFP. We verify the existance of this directory and then +; copy the WFP into the CDS and set up the ID field to point to the +; directory cluster. +; o Net CDS. We form the path from the root (including network prefix) +; and verify its existance (via DOS_Chdir). If successful, we copy the +; WFP back into the CDS. +; o SUBST'ed CDS. This is no different than the local, simple CDS. +; o JOIN'ed CDS. This is trouble as there are two CDS's at work. If we +; call TransPath, we will get the PHYSICAL CDS that the path refers to +; and the PHYSICAL WFP that the input path refers to. This is perfectly +; good for the validation but not for currency. We call TransPathNoSet +; to process the path but to return the logical CDS and the logical +; path. We then copy the logical path into the logical CDS. +; +; Inputs: +; DS:DX Points to asciz name +; Returns: +; STD XENIX Return +; AX = chdir_path_not_found if error + + procedure $CHDIR,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup + MOV DI,OFFSET DOSGroup:OpenBuf ; spot for translated name + MOV SI,DX ; get source + Invoke TransPath ; go munge the path and get real CDS + JNC ChDirCrack ; no errors, try path +ChDirErrP: + MOV AL,error_path_not_found +ChdirErr: + transfer SYS_Ret_Err ; oops! + +ChDirCrack: + Assume DS:DOSGroup + CMP cMeta,-1 ; No meta chars allowed. + JNZ ChDirErrP +; +; We cannot do a ChDir (yet) on a raw CDS. This is treated as a path not +; found. +; + LES DI,ThisCDS + CMP DI,-1 ; if (ThisCDS == NULL) + JZ ChDirErrP ; error (); + ; + ; Find out if the directory exists. + ; + Invoke DOS_ChDir + JC ChDirErr +; +; Get back CDS to see if a join as seen. Set the currency pointer (only if +; not network). If one was seen, all we need to do is copy in the text +; + LES DI,ThisCDS + TEST ES:[DI].curdir_flags,curdir_splice + JZ GotCDS +; +; The CDS was joined. Let's go back and grab the logical CDS. +; + SaveReg ; save CDS and cluster... + Invoke Get_User_Stack ; get original text + ASSUME DS:NOTHING + MOV DI,[SI.User_DX] + MOV DS,[SI.User_DS] + MOV SI,OFFSET DOSGroup:OpenBuf ; spot for translated name + XCHG SI,DI + XOR AL,AL ; do no splicing + SaveReg + Invoke TransPathNoSet ; Munge path + RestoreReg + Assume DS:DOSGroup +; +; There should NEVER be an error here. +; +IF FALSE + JNC SKipErr + fmt <>,<>,<"$p: Internal CHDIR error\n"> +SkipErr: +ENDIF + LES DI,ThisCDS ; get new CDS + MOV ES:[DI].curdir_ID,-1 ; no valid cluster here... + RestoreReg +; +; ES:DI point to the physical CDS, CX is the ID (local only) +; +GotCDS: +; +; wfp_start points to the text. See if it is long enough +; + CALL Check_PathLen ;PTM. ;AN000; + JA ChDirErrP + TEST ES:[DI].curdir_flags,curdir_isnet + JNZ SkipRecency + TEST ES:[DI].curdir_flags,curdir_splice ;PTM. for Join and Subst ;AN000; + JZ setdirclus ;PTM. ;AN000; + MOV CX,-1 ;PTM. ;AN000; +setdirclus: + MOV ES:[DI].curdir_id,CX + LES DI,ThisCDS ; get logical CDS +SkipRecency: + invoke FStrCpy + XOR AL,AL + transfer Sys_Ret_OK +EndProc $CHDIR + +BREAK <$MkDir - Make a directory entry> +; Inputs: +; DS:DX Points to asciz name +; Function: +; Make a new directory +; Returns: +; STD XENIX Return +; AX = mkdir_path_not_found if path bad +; AX = mkdir_access_denied If +; Directory cannot be created +; Node already exists +; Device name given +; Disk or directory(root) full + + procedure $MKDIR,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup + MOV SI,OFFSET DOSGroup:DOS_MkDir +DoDirCall: + MOV DI,OFFSET DOSGroup:OpenBuf ; spot for translated name + SaveReg + MOV SI,DX ; get source + Invoke TransPath ; go munge the path + RestoreReg + JNC MkDirCrack ; no errors, try path +MkErrP: + MOV AL,error_Path_Not_Found ; oops! +MkErr: + transfer Sys_Ret_Err +MkDirCrack: + CMP cMeta,-1 + JNZ MkErrP + + PUSH SI ;PTM. ;AN000; + CALL Check_PathLen ;PTM. check path len > 67 ? ;AN000; + POP SI ;PTM. ;AN000; + JBE pathok ;PTM. ;AN000; + MOV AL,error_Access_Denied ;PTM. ops! + transfer Sys_Ret_Err ;PTM. +pathok: + CALL SI ; go get file + ASSUME ES:NOTHING + JC MkErr ; no errors + transfer Sys_Ret_OK +EndProc $MKDIR + +; Inputs: +; nothing +; Function: +; check if final path length greater than 67 +; Returns: +; Above flag set if > 67 + + procedure Check_PathLen,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup + + MOV SI,Wfp_Start + entry Check_PathLen2 + Context + SaveReg + invoke DStrLen + CMP CX,DirStrLen + RestoreReg + ret +EndProc Check_PathLen +CODE ENDS +END + \ No newline at end of file diff --git a/v4.0/src/DOS/PRINT.ASM b/v4.0/src/DOS/PRINT.ASM new file mode 100644 index 0000000..c2bbe55 --- /dev/null +++ b/v4.0/src/DOS/PRINT.ASM @@ -0,0 +1,199 @@ +; SCCSID = @(#)print.asm 1.1 85/04/10 +; +; PFMT - formatted output. Calling sequence: +; PUSH BP +; PUSH fmtstr +; MOV BP,SP +; PUSH args +; CALL PFMT +; ADD SP,n +; POP BP +; +; The format string contains format directives and normal output characters +; much like the PRINTF for C. We utilize NO format widths. Special chars +; and strings are: +; +; $x output a hex number +; $s output an offset string +; $c output a character +; $S output a segmented string +; $p output userid/processid +; \t output a tab +; \n output a CRLF +; +; The format string must be addressable via CS +; + +Procedure PFMT,NEAR + SaveReg + MOV AX,8007h + INT 2Ah + PUSH CS + POP DS + SUB BP,2 + Call FMTGetArg + MOV SI,AX +FmtLoop: + LODSB + OR AL,AL + JZ FmtDone + CMP AL,'$' + JZ FmtOpt + CMP AL,'\' + JZ FmtChr +FmtOut: + CALL Out + JMP FmtLoop +Out: + SaveReg + INT 29h + RestoreReg + return +FmtDone: + MOV AX,8107h + INT 2Ah + RestoreReg + RET +; +; \ leads in a special character. See what the next char is. +; +FmtChr: LODSB + OR AL,AL ; end of string + JZ fmtDone + CMP AL,'n' ; newline + JZ FmtCRLF + CMP AL,'t' ; tab + JNZ FmtOut + MOV AL,9 + JMP FmtOut +FmtCRLF:MOV AL,13 + CALL Out + MOV AL,10 + JMP FmtOut +; +; $ leads in a format specifier. +; +FmtOpt: LODSB + CMP AL,'x' ; hex number + JZ FmtX + CMP AL,'c' ; single character + JZ FmtC + CMP AL,'s' ; offset string + JZ FmtSoff + CMP AL,'S' ; segmented string + JZ FmtSseg + CMP AL,'p' + JZ FmtUPID + JMP FmtOut +FmtX: + Call FMTGetArg + MOV BX,AX + CALL MNUM + JMP FmtLoop +FmtC: + Call FmtGetArg + CALL Out + JMP FmtLoop +FmtSoff: + SaveReg + Call FmtGetArg + MOV SI,AX + CALL fmtsout + RestoreReg + JMP FmtLoop +FmtSSeg: + SaveReg + CALL FMTGetArg + MOV DS,AX + CALL FMTGetArg + MOV SI,AX + CALL fmtsout + RestoreReg + JMP FmtLoop +FmtUPID: + SaveReg + MOV BX,0 + MOV DS,BX + MOV DS,DS:[82h] + ASSUME DS:DOSGroup + MOV BX,User_ID + CALL MNUM + MOV AL,':' + CALL OUT + MOV BX,Proc_ID + CALL MNUM + RestoreReg + Assume DS:NOTHING + JMP FmtLoop +EndProc PFMT + +Procedure FMTGetArg,NEAR + MOV AX,[BP] + SUB BP,2 + return +EndProc FMTGetArg + +Procedure FmtSOut,NEAR + LODSB + OR AL,AL + retz + CALL OUT + JMP FmtSOut +EndProc FMTSout + +; +; MOut - output a message via INT 29h +; Inputs: BX points to bytes to output relative to CS +; Outputs: message +; Registers modified: BX +Procedure MOut,Near + ASSUME DS:NOTHING,SS:NOTHING,ES:NOTHING + PUSHF + SaveReg + PUSH CS + POP DS + MOV SI,BX + Call FMTSout + RestoreReg + POPF + return +EndProc MOut + +; MNum - output a number in BX +; Inputs: BX contains a number +; Outputs: number in hex appears on screen +; Registers modified: BX + +Procedure MNum,NEAR + ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + PUSHF + SaveReg + PUSH SS + POP ES + SUB SP,6 + MOV DI,SP ; p = MNumBuf; + SaveReg + MOV CX,4 ; for (i=0; i < 4; i++) +DLoop: SaveReg + MOV CX,4 ; rotate(n, 4); + ROL BX,CL + RestoreReg + MOV AL,BL + AND AL,0Fh + ADD AL,'0' + CMP AL,'9' + JBE Nok + ADD AL,'A'-'0'-10 +Nok: STOSB ; *p++ = "0123456789ABCDEF"[n]; + LOOP DLoop + XOR AL,AL + STOSB ; *p++ = 0; + RestoreReg + PUSH ES + POP DS + CALL FMTSOUT ; mout (mNumBuf); + ADD SP,6 + RestoreReg + POPF + return +EndProc MNum diff --git a/v4.0/src/DOS/PROC.ASM b/v4.0/src/DOS/PROC.ASM new file mode 100644 index 0000000..1e54034 --- /dev/null +++ b/v4.0/src/DOS/PROC.ASM @@ -0,0 +1,187 @@ +; SCCSID = @(#)proc.asm 1.1 85/04/10 +TITLE IBMPROC - process maintenance +NAME IBMPROC + +; +; Process related system calls and low level routines for DOS 2.X. +; I/O specs are defined in DISPATCH. +; +; $WAIT +; $EXEC +; $Keep_process +; Stay_resident +; $EXIT +; $ABORT +; abort_inner +; +; Modification history: +; +; Created: ARR 30 March 1983 +; + +.xlist +; +; get the appropriate segment definitions +; +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +.cref +.list + +SAVEXIT EQU 10 + + i_need CurrentPDB,WORD + i_need CreatePDB,BYTE + i_need Exit_type,BYTE + i_need INDOS,BYTE + i_need DMAADD,DWORD + i_need DidCTRLC,BYTE + i_need exit_type,BYTE + i_need exit_code,WORD + i_need OpenBuf,128 + I_need EXTERR_LOCUS,BYTE ; Extended Error Locus + +SUBTTL $WAIT - return previous process error code +PAGE +; +; process control data +; + i_need exit_code,WORD ; code of exit + +; +; Assembler usage: +; MOV AH, WaitProcess +; INT int_command +; AX has the exit code + procedure $WAIT,NEAR + ASSUME DS:NOTHING,ES:NOTHING + XOR AX,AX + XCHG AX,exit_code + transfer SYS_RET_OK +EndProc $WAIT + +include exec.asm + +SUBTTL Terminate and stay resident handler +PAGE +; +; Input: DX is an offset from CurrentPDB at which to +; truncate the current block. +; +; output: The current block is truncated (expanded) to be [DX+15]/16 +; paragraphs long. An exit is simulated via resetting CurrentPDB +; and restoring the vectors. +; + procedure $Keep_process,NEAR + ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGROUP + + PUSH AX ; keep exit code around + MOV BYTE PTR [Exit_type],Exit_keep_process + MOV ES,[CurrentPDB] + CMP DX,6h ; keep enough space around for system + JAE Keep_shrink ; info + MOV DX,6h +keep_shrink: + MOV BX,DX + PUSH BX + PUSH ES + invoke $SETBLOCK ; ignore return codes. + POP DS + POP BX + JC keep_done ; failed on modification + MOV AX,DS + ADD AX,BX + MOV DS:[PDB_block_len],AX + +keep_done: + POP AX + JMP SHORT exit_inner ; and let abort take care of the rest + +EndProc $Keep_process + + procedure Stay_resident,NEAR + ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + MOV AX,(Keep_process SHL 8) + 0 ; Lower part is return code + ADD DX,15 + RCR DX,1 + MOV CL,3 + SHR DX,CL + + transfer COMMAND +EndProc Stay_resident + +SUBTTL $EXIT - return to parent process +PAGE +; +; Assembler usage: +; MOV AL, code +; MOV AH, Exit +; INT int_command +; Error return: +; None. +; + procedure $EXIT,NEAR + ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGROUP + XOR AH,AH + XCHG AH,BYTE PTR [DidCTRLC] + OR AH,AH + MOV BYTE PTR [Exit_type],exit_terminate + JZ exit_inner + MOV BYTE PTR [Exit_type],exit_ctrl_c + + entry Exit_inner + + invoke get_user_stack + PUSH [CurrentPDB] + POP [SI.user_CS] + JMP SHORT abort_inner +EndProc $EXIT + +BREAK <$ABORT -- Terminate a process> + +; Inputs: +; user_CS:00 must point to valid program header block +; Function: +; Restore terminate and Cntrl-C addresses, flush buffers and transfer to +; the terminate address +; Returns: +; TO THE TERMINATE ADDRESS + + procedure $ABORT,NEAR +ASSUME DS:NOTHING,ES:NOTHING + + XOR AL,AL + MOV [exit_type],exit_abort + +; +; abort_inner must have AL set as the exit code! The exit type is retrieved +; from exit_type. Also, the PDB at user_CS needs to be correct as the one +; that is terminating. +; + entry abort_inner + + MOV AH,[exit_type] + MOV [exit_code],AX + invoke Get_user_stack + MOV DS,[SI.user_CS] ; set up old interrupts + XOR AX,AX + MOV ES,AX + MOV SI,SAVEXIT + MOV DI,addr_int_terminate + MOVSW + MOVSW + MOVSW + MOVSW + MOVSW + MOVSW + transfer reset_environment +EndProc $ABORT + +CODE ENDS + END diff --git a/v4.0/src/DOS/RENAME.ASM b/v4.0/src/DOS/RENAME.ASM new file mode 100644 index 0000000..c7d6caf --- /dev/null +++ b/v4.0/src/DOS/RENAME.ASM @@ -0,0 +1,434 @@ +; SCCSID = @(#)rename.asm 1.1 85/04/10 +TITLE DOS_RENAME - Internal RENAME call for MS-DOS +NAME DOS_RENAME +; Low level routine for renaming files +; +; DOS_RENAME +; +; Modification history: +; +; Created: ARR 30 March 1983 +; + +; +; get the appropriate segment definitions +; +.xlist +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +.cref +.list + +Installed = TRUE + + i_need RENAMEDMA,BYTE + i_need AUXSTACK,BYTE + i_need DESTSTART,WORD + i_need DIRSTART,WORD + i_need CURBUF,DWORD + I_need NAME1,BYTE + i_need NAME2,BYTE + i_need WFP_START,WORD + i_need REN_WFP,WORD + i_need CURR_DIR_END,WORD + i_need DMAADD,DWORD + i_need THISCDS,DWORD + i_need THISDPB,DWORD + i_need THISSFT,DWORD + i_need CREATING,BYTE + i_need THISDRV,BYTE + i_need ATTRIB,BYTE + i_need FOUND_DEV,BYTE + i_need FAILERR,BYTE + i_need EXTERR_LOCUS,BYTE + i_need SAVE_BX,WORD + +; Inputs: +; [WFP_START] Points to SOURCE WFP string ("d:/" must be first 3 +; chars, NUL terminated) +; [CURR_DIR_END] Points to end of Current dir part of string [SOURCE] +; ( = -1 if current dir not involved, else +; Points to first char after last "/" of current dir part) +; [REN_WFP] Points to DEST WFP string ("d:/" must be first 3 +; chars, NUL terminated) +; [THISCDS] Points to CDS being used +; (Low word = -1 if NUL CDS (Net direct request)) +; [SATTRIB] Is attribute of search, determines what files can be found +; Function: +; Rename the specified file(s) +; NOTE: This routine uses most of AUXSTACK as a temp buffer. +; Outputs: +; CARRY CLEAR +; OK +; CARRY SET +; AX is error code +; error_file_not_found +; No match for source, or dest path invalid +; error_not_same_device +; Source and dest are on different devices +; error_access_denied +; Directory specified (not simple rename), +; Device name given, Destination exists. +; NOTE: In third case some renames may have +; been done if metas. +; error_path_not_found +; Bad path (not in curr dir part if present) +; SOURCE ONLY +; error_bad_curr_dir +; Bad path in current directory part of path +; SOURCE ONLY +; error_sharing_violation +; Deny both access required, generates an INT 24. +; DS preserved, others destroyed + + procedure DOS_RENAME,NEAR + DOSAssume CS,,"DOS_Rename" + ASSUME ES:NOTHING + + Invoke TestNet + JNC LOCAL_RENAME +; invoke OWN_SHARE2 ;IFS. IFS owns share ? ;AN000; +; JZ ifsshare ;IFS. yes ;AN000; +; PUSH WORD PTR [DMAADD+2] ;IFS. save DMAADD ;AN000; +; PUSH WORD PTR [DMAADD] ;IFS. ;AN000; +; +; invoke IFS_SEARCH_FIRST ;IFS. search source name ;AN000; +; JC nofiles ;IFS. not found ;AN000; +rename_next_file: +; invoke IFS_REN_DEL_CHECK ;IFS. do share check ;AN000; +; JNC share_okok ;IFS. share ok ;AN000; +; MOV AX,error_sharing_violation ;IFS. share error ;AN000; +; JMP SHORT nofiles ;IFS. ;AN000; +share_okok: +; PUSH CS ;IFS. ;AN000; +; POP ES ;IFS. ;AN000; +; MOV SI,[REN_WFP] ;IFS. ds:si -> destination name ;AN000; +; MOV BX,SI ;IFS. ;AN000; +fndnxt: ;IFS. ;AN000; +; LODSB ;IFS. ;AN000; +; CMP AL,0 ;IFS. ;AN000; +; JNZ fndnxt ;IFS. ;AN000; +; MOV DI,SI ;IFS. es:di -> end of destinatio ;AN000; +; ADD BX,2 ;IFS. ;AN000; +; invoke SkipBack ;IFS. ;AN000; +; INC DI ;IFS. es:di -> last component of ;AN000; +; MOV SI,DI ;IFS. dstination ;AN000; +; MOV BX,[SAVE_BX] ;IFS. ds:bx -> last component of ;AN000; +; CALL NEW_RENAME ;IFS. source ;AN000; +; MOV AX,(multNET SHL 8) OR 17 ;IFS. replace ? chars with ;AN000; +; INT 2FH ;IFS. source and issue RENAME ;AN000; +; JC nofiles ;IFS. error ;AN000; +; invoke DOS_SEARCH_NEXT ;IFS. serch next source ;AN000; +; JNC rename_next_file ;IFS. rename next ;AN000; +; CLC ;IFS. no more files ;AN000; +nofiles: +; POP WORD PTR [DMAADD] ;IFS. restore DMAADD ;AN000; +; POP WORD PTR [DMAADD+2] ;IFS. ;AN000; +; ret ;IFS. return ;AN000; +ifsshare: + +IF NOT Installed + transfer NET_RENAME +ELSE + MOV AX,(multNET SHL 8) OR 17 + INT 2FH + return +ENDIF + +LOCAL_RENAME: + MOV [EXTERR_LOCUS],errLOC_Disk + MOV SI,[WFP_START] + MOV DI,[REN_WFP] + MOV AL,BYTE PTR [SI] + MOV AH,BYTE PTR [DI] + OR AX,2020H ; Lower case + CMP AL,AH + JZ SAMEDRV + MOV AX,error_not_same_device + STC + return + +SAMEDRV: + PUSH WORD PTR [DMAADD+2] + PUSH WORD PTR [DMAADD] + MOV WORD PTR [DMAADD+2],DS + MOV WORD PTR [DMAADD],OFFSET DOSGROUP:RENAMEDMA + MOV [Found_dev],0 ; Rename fails on DEVS, assume not a dev + EnterCrit critDisk + invoke DOS_SEARCH_FIRST ; Sets [NoSetDir] to 1, [CURBUF+2]:BX + ; points to entry + JNC Check_Dev + CMP AX,error_no_more_files + JNZ GOTERR + MOV AX,error_file_not_found +GOTERR: + STC +RENAME_POP: + POP WORD PTR [DMAADD] + POP WORD PTR [DMAADD+2] + LeaveCrit critDisk + return + +Check_dev: + MOV AX,error_access_denied ; Assume error + + PUSH DS ;PTM. ;AN000; + LDS SI,[DMAADD] ;PTM. chek if source a dir ;AN000; + ADD SI,find_buf_attr ;PTM. ;AN000; + TEST [SI.dir_attr],attr_directory ;PTM. ;AN000; + JZ notdir ;PTM. ;AN000; + MOV SI,[REN_WFP] ;PTM. if yes, make sure path ;AN000; + invoke Check_Pathlen2 ;PTM. length < 67 ;AN000; +notdir: + POP DS ;PTM. ;AN000; + JA GOTERR ;PTM. ;AN000; + + CMP [Found_dev],0 + JNZ GOTERR +; At this point a source has been found. There is search continuation info (a +; la DOS_SEARCH_NEXT) for the source at RENAMEDMA, together with the first +; directory entry found. +; [THISCDS], [THISDPB], and [THISDRV] are set and will remain correct +; throughout the RENAME since it is known at this point that the source and +; destination are both on the same device. +; [SATTRIB] is also set. + MOV SI,BX + ADD SI,dir_first + invoke REN_DEL_Check + JNC REN_OK1 + MOV AX,error_sharing_violation + JMP RENAME_POP + +REN_OK1: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + invoke FastOpen_Delete ; delete dir info in fastopen DOS 3.3 + MOV SI,[REN_WFP] ; Swap source and destination + MOV [WFP_START],SI + MOV [CURR_DIR_END],-1 ; No current dir on dest + MOV WORD PTR [CREATING],0E5FFH ; Creating, not DEL *.* + ; A rename is like a CREATE_NEW as far + ; as the destination is concerned. + invoke GetPathNoSet +; If this Getpath fails due to file not found, we know all renames will work +; since no files match the destination name. If it fails for any other +; reason, the rename fails on a path not found, or whatever (also fails if +; we find a device or directory). If the Getpath succeeds, we aren't sure +; if the rename should fail because we haven't built an explicit name by +; substituting for the meta chars in it. In this case the destination file +; spec with metas is in [NAME1] and the explicit source name is at RENAMEDMA +; in the directory entry part. + JC NODEST +;; JZ BAD_ACC ; Dest string is a directory ;AC000; + OR AH,AH ; Device? + JNS SAVEDEST ; No, continue +BAD_ACC: + MOV AX,error_access_denied + STC +RENAME_CLEAN: + PUSHF ; Save carry state + PUSH AX ; and error code (if carry set) + MOV AL,[THISDRV] + invoke FLUSHBUF + POP AX + CMP [FAILERR],0 + JNZ BAD_ERR ; User FAILed to I 24 + POPF + JMP RENAME_POP + +BAD_ERR: + POP AX ; Saved flags + MOV AX,error_path_not_found + JMP GOTERR + +NODEST: + JNZ BAD_PATH + CMP [FAILERR],0 + JNZ BAD_PATH ; Search for dest failed because user FAILed on + ; I 24 + OR CL,CL + JNZ SAVEDEST +BAD_PATH: + MOV AX,error_path_not_found + STC + JMP RENAME_POP + +SAVEDEST: + Context ES + MOV DI,OFFSET DOSGROUP:NAME2 + MOV SI,OFFSET DOSGROUP:NAME1 + MOV CX,11 + REP MOVSB ; Save dest with metas at NAME2 + MOV AX,[DIRSTART] + MOV [DESTSTART],AX +BUILDDEST: + Context ES ; needed due to JMP BUILDDEST below + MOV BX,OFFSET DOSGROUP:RENAMEDMA + 21 ; Source of replace chars + MOV DI,OFFSET DOSGROUP:NAME1 ; Real dest name goes here + MOV SI,OFFSET DOSGROUP:NAME2 ; Raw dest + MOV CX,11 + CALL NEW_RENAME ;IFS. replace ? chars ;AN000; + + MOV [ATTRIB],attr_all ; Stop duplicates with any attributes + MOV [CREATING],0FFH + invoke DEVNAME ; Check if we built a device name + ASSUME ES:NOTHING + JNC BAD_ACC + MOV BX,[DESTSTART] + LES BP,[THISDPB] + invoke SetDirSrch ; Reset search to start of dir + JC BAD_ACC ; Screw up + invoke FINDENTRY ; See if new name already exists + JNC BAD_ACC ; Error if found + CMP [FAILERR],0 + JNZ BAD_ACCJ ; Find failed because user FAILed to I 24 + MOV AX,[DESTSTART] ; DIRSTART of dest + CMP AX,WORD PTR [RENAMEDMA + 15] ; DIRSTART of source + JZ SIMPLE_RENAME ; If =, just give new name + + MOV AL,[RENAMEDMA + 21 + dir_attr] + TEST AL,attr_directory + JNZ BAD_ACCJ ; Can only do a simple rename on dirs, + ; otherwise the . and .. entries get + ; wiped. + MOV [ATTRIB],AL + MOV WORD PTR [THISSFT+2],DS + MOV SI,OFFSET DOSGROUP:AUXSTACK - SIZE SF_ENTRY + MOV WORD PTR [THISSFT],SI + MOV [SI].sf_mode,sharing_compat+open_for_both + XOR CX,CX ; Set "device ID" for call into makenode + invoke RENAME_MAKE ; This is in mknode + JNC GOT_DEST +BAD_ACCJ: + JMP BAD_ACC + +GOT_DEST: + SaveReg + LES DI,ThisSFT ; Rename_make entered this into sharing + Invoke ShareEnd ; we need to remove it. + RestoreReg +; A zero length entry with the correct new name has now been made at +; [CURBUF+2]:BX. + LES DI,[CURBUF] + Assert ISBUF,,"Got_Dest" + + TEST ES:[DI.buf_flags],buf_dirty ;LB. if already dirty ;AN000; + JNZ yesdirty ;LB. don't increment dirty count ;AN000; + invoke INC_DIRTY_COUNT ;LB. ;AN000; + OR ES:[DI.buf_flags],buf_dirty +yesdirty: + MOV DI,BX + ADD DI,dir_attr ; Skip name + MOV SI,OFFSET DOSGROUP:RENAMEDMA + 21 + dir_attr + MOV CX,(SIZE dir_entry) - dir_attr + REP MOVSB + CALL GET_SOURCE + JC RENAME_OVER + MOV DI,BX + MOV ES,WORD PTR [CURBUF+2] + MOV AL,0E5H + STOSB ; "free" the source + JMP SHORT DIRTY_IT + +SIMPLE_RENAME: + CALL GET_SOURCE ; Get the source back + JC RENAME_OVER + MOV DI,BX + MOV ES,WORD PTR [CURBUF+2] + MOV SI,OFFSET DOSGROUP:NAME1 ; New Name + MOV CX,11 + REP MOVSB +DIRTY_IT: + MOV DI,WORD PTR [CURBUF] + + TEST ES:[DI.buf_flags],buf_dirty ;LB. if already dirty ;AN000; + JNZ yesdirty2 ;LB. don't increment dirty count ;AN000; + invoke INC_DIRTY_COUNT ;LB. ;AN000; + OR ES:[DI.buf_flags],buf_dirty +yesdirty2: + Assert ISBUF,,"Dirty_it" +NEXT_SOURCE: + MOV SI,OFFSET DOSGROUP:RENAMEDMA + 1 ;Name +; +; WARNING! Rename_Next leaves the disk critical section *ALWAYS*. We need +; to enter it before going to RENAME_Next. +; + EnterCrit critDisk + MOV [CREATING],0 ; Correct setting for search (we changed it + ; to FF when we made the prev new file). + invoke RENAME_NEXT +; +; Note, now, that we have exited the previous ENTER and so are back to where +; we were before. +; + JC RENAME_OVER + LEA SI,[BX].dir_First + invoke REN_DEL_Check + JNC REN_OK2 + MOV AX,error_sharing_violation + JMP RENAME_CLEAN + +REN_OK2: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + invoke FastOpen_Delete ; delete dir info in fastopen DOS 3.3 + JMP BUILDDEST + +RENAME_OVER: + CLC + JMP RENAME_CLEAN + +; Inputs: +; RENAMEDMA has source info +; Function: +; Re-find the source +; Output: +; [CURBUF] set +; [CURBUF+2]:BX points to entry +; Carry set if error (currently user FAILed to I 24) +; DS preserved, others destroyed + +GET_SOURCE: + DOSAssume CS,,"Get_Source" + ASSUME ES:NOTHING + + MOV BX,WORD PTR [RENAMEDMA + 15] ; DirStart + LES BP,ThisDPB + invoke SetDirSrch + retc + invoke StartSrch + MOV AX,WORD PTR [RENAMEDMA + 13] ; Lastent + invoke GetEnt + return + +EndProc DOS_RENAME + +;Input: DS:SI -> raw string with ? +; ES:DI -> destination string +; DS:BX -> source string +;Function: replace ? chars of raw string with chars in source string and +; put in destination string +;Output: ES:DI-> new string + + + + procedure NEW_RENAME,NEAR + DOSAssume CS,,"DOS_Rename" + ASSUME ES:NOTHING +NEWNAM: + LODSB + CMP AL,"?" + JNZ NOCHG + MOV AL,[BX] ; Get replace char +NOCHG: + STOSB + INC BX ; Next replace char + LOOP NEWNAM + return + +EndProc NEW_RENAME + +CODE ENDS + END diff --git a/v4.0/src/DOS/ROM.ASM b/v4.0/src/DOS/ROM.ASM new file mode 100644 index 0000000..ca34409 --- /dev/null +++ b/v4.0/src/DOS/ROM.ASM @@ -0,0 +1,938 @@ +; SCCSID = @(#)rom.asm 1.1 85/04/10 +TITLE ROM - Miscellaneous routines +NAME ROM +; Misc Low level routines for doing simple FCB computations, Cache +; reads and writes, I/O optimization, and FAT allocation/deallocation +; +; SKPCLP +; FNDCLUS +; BUFSEC +; BUFRD +; BUFWRT +; NEXTSEC +; OPTIMIZE +; FIGREC +; ALLOCATE +; RESTFATBYT +; RELEASE +; RELBLKS +; GETEOF +; +; Modification history: +; +; Created: ARR 30 March 1983 +; + +; +; get the appropriate segment definitions +; +.xlist +include dosseg.asm +include fastseek.inc ; DOS 4.00 +include fastxxxx.inc ; DOS 4.00 +include version.inc + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +include EA.inc +.cref +.list + + i_need CLUSNUM,WORD + i_need NEXTADD,WORD + i_need LASTPOS,WORD + i_need SECCLUSPOS,BYTE + i_need FATBYT,WORD + i_need THISSFT,DWORD + i_need TRANS,BYTE + i_need BYTCNT1,WORD + i_need CURBUF,DWORD + i_need BYTSECPOS,WORD + i_need DMAADD,WORD + i_need SECPOS,DWORD ;F.C. >32mb + i_need VALSEC,DWORD ;F.C. >32mb + i_need ALLOWED,BYTE + i_need FSeek_drive,BYTE ; DOS 3.4 + i_need FSeek_firclus,WORD ; DOS 3.4 + i_need FSeek_logclus,WORD ; DOS 3.4 + i_need FSeek_logsave,WORD ; DOS 3.4 + i_need FastSeekFlg,BYTE ; DOS 3.4 + i_need XA_condition,BYTE ; DOS 3.4 + i_need HIGH_SECTOR,WORD ; DOS 3.4 + i_need DISK_FULL,BYTE ; DOS 3.4 + i_need Temp_VAR2,WORD ; DOS 3.4 + + + +Break + +; Inputs: +; CX = No. of clusters to skip +; ES:BP = Base of drive parameters +; [THISSFT] point to SFT +; Outputs: +; BX = Last cluster skipped to +; CX = No. of clusters remaining (0 unless EOF) +; DX = Position of last cluster +; Carry set if error (currently user FAILed to I 24) +; DI destroyed. No other registers affected. + + procedure FNDCLUS,NEAR + DOSAssume CS,,"FndClus" + ASSUME ES:NOTHING + + Assert ISDPB,,"FndCLus" +;; 10/31/86 FastSeek + PUSH ES + LES DI,[THISSFT] + Assert ISSFT,,"FndClus" + MOV [FSeek_logclus],CX ; presume CX is the position ;AN000; + MOV BX,ES:[DI.sf_lstclus] + MOV DX,ES:[DI.sf_cluspos] +;; 10/31/86 FastSeek + OR BX,BX + JNZ YCLUS + JMP NOCLUS +YCLUS: + SUB CX,DX + JNB FINDIT + ADD CX,DX + XOR DX,DX + MOV BX,ES:[DI.sf_firclus] +FINDIT: +;; 10/31/86 FastSeek + + + POP ES + OR CX,CX + JNZ skpclp + JMP RET10 + +entry SKPCLP + TEST [FastSeekflg],Fast_yes ; fastseek installed? ;AN000; + JZ do_norm ; no ;AN000; + TEST [FastSeekflg],FS_begin ; do fastseek ;AN000; + JZ do_norm ; no ;AN000; + TEST [FastSeekflg],FS_insert ; is in insert mode ? ;AN000; + JNZ do_norm ; yes ;AN000; + MOV [Temp_Var2],BX ; save physical cluster ;AN000; + ; PTR P005079 +SKPCLP2: + invoke FastSeek_Lookup ; ask for next cluster # ;AN000; + JNC clusfound ; yes, we got it ;AN000; + CMP DI,1 ; valid drive ,e.g. C,D... ;AN000; + JNZ par_found ; yes, ;AN000; + AND [FastSeekflg],Fast_yes ; no more, fastseek ;AN000; + JMP SHORT do_norm ;AN000; + ;AN000; +par_found: + CALL FS_Trunc_EOF ; check EOF and truncate ;AN000; + JNC SKPCLP2 ; redo lookup ;AN000; +noteof: + OR [FastSeekflg],FS_insert ; no, start to insert ;AN000; + CMP DX,[FSeek_logsave] ; is current better than new? ;AN000; + JBE OnCache ; no, let's use new ;AN000; + MOV [FSeek_logclus],DX ; use current ;AN000; + MOV BX,[Temp_Var2] ; retore pysical cluster ;AN000; + MOV DI,BX ; insert cureent cluster ;AN000; + invoke FastSeek_Insert ; insert cluster # to ;AN000; + INC [FSeek_logclus] ; get next inserted position ;AN000; + JMP SHORT do_norm +OnCache: + MOV CX,[FSeek_logclus] ; get the number of clusters ;AN000; + SUB CX,[FSeek_logsave] ; we need to skip ;AN000; + MOV DX,[FSeek_logsave] ; cluster position ;AN000; +dodo: + INC [FSeek_logsave] ; get next inserted position ;AN000; + PUSH [FSeek_logsave] ; logclus=logsave ;AN000; + POP [FSeek_logclus] ;AN000; + +do_norm: + + invoke UNPACK + retc + + invoke FastSeek_Insert ; insert cluster # to ;AN000; +cluss: ;AN000; + PUSH BX ; FastSeek ;AN000; + MOV BX,DI + Invoke IsEOF + POP BX + JAE RET10 + XCHG BX,DI + INC DX + INC [FSeek_logclus] ; increment for next inserted ;AN000; + LOOP SKPCLPX + JMP short RET10 +SKPCLPX: + JMP SKPCLP +RET10: ;AN000; + AND [FastSeekflg],FS_no_insert ; clear insert mode + CLC + return +NOCLUS: + POP ES + INC CX + DEC DX + CLC + return +clusfound: + MOV DX,[FSeek_logclus] ; get cluster position ;AN000; + MOV BX,[FSeek_logsave] ; bx=previous cluster # PTM ;AN000; + DEC DX ;AN000; + MOV CX,1 ; we found it ;AN000; + JMP cluss ;AN000; + +EndProc FNDCLUS + +Break + +; Inputs: +; AH = priority of buffer +; AL = 0 if buffer must be read, 1 if no pre-read needed +; ES:BP = Base of drive parameters +; [CLUSNUM] = Physical cluster number +; [SECCLUSPOS] = Sector position of transfer within cluster +; [BYTCNT1] = Size of transfer +; Function: +; Insure specified sector is in buffer, flushing buffer before +; read if necessary. +; Outputs: +; ES:DI = Pointer to buffer +; SI = Pointer to transfer address +; CX = Number of bytes +; [NEXTADD] updated +; [TRANS] set to indicate a transfer will occur +; Carry set if error (user FAILed to I 24) + + procedure BUFSEC,NEAR + DOSAssume CS,,"BufSec" + ASSUME ES:NOTHING + + Assert ISDPB,,"BufSec" + MOV DX,[CLUSNUM] + MOV BL,[SECCLUSPOS] + MOV [ALLOWED],allowed_FAIL + allowed_RETRY + allowed_IGNORE + CALL FIGREC + invoke GETBUFFR + retc + MOV BYTE PTR [TRANS],1 ; A transfer is taking place + MOV SI,[NEXTADD] + MOV DI,SI + MOV CX,[BYTCNT1] + ADD DI,CX + MOV [NEXTADD],DI + LES DI,[CURBUF] + Assert ISBUF,,"BufSec" + OR ES:[DI.buf_flags],buf_isDATA + LEA DI,[DI].BUFINSIZ ; Point to buffer + ADD DI,[BYTSECPOS] + CLC + return +EndProc BUFSEC + +Break + +; Do a partial sector read via one of the system buffers +; ES:BP Points to DPB +; Carry set if error (currently user FAILed to I 24) + + procedure BUFRD,NEAR + DOSAssume CS,,"BufRd" + ASSUME ES:NOTHING + + Assert ISDPB,,"BufRd" + PUSH ES + MOV AX,0 + CALL BUFSEC + JNC BUF_OK +BUF_IO_FAIL: + POP ES + JMP SHORT RBUFPLACED + +BUF_OK: + MOV BX,ES + MOV ES,[DMAADD+2] + MOV DS,BX +ASSUME DS:NOTHING + XCHG DI,SI + SHR CX,1 + JNC EVENRD + MOVSB +EVENRD: + REP MOVSW + POP ES + LDS DI,[CURBUF] + Assert ISBUF,,"BufRD/EvenRD" + LEA BX,[DI.BufInSiz] + SUB SI,BX ; Position in buffer + invoke PLACEBUF + Assert ISDPB,,"BufRD/EvenRD" + CMP SI,ES:[BP.dpb_sector_size] ; Read Last byte? + JB RBUFPLACEDC ; No, leave buf where it is + invoke PLACEHEAD ; Make it prime candidate for chucking + ; even though it is MRU. +RBUFPLACEDC: + CLC +RBUFPLACED: + PUSH SS + POP DS + return +EndProc BUFRD + +; Do a partial sector write via one of the system buffers +; ES:BP Points to DPB +; Carry set if error (currently user FAILed to I 24) + + procedure BUFWRT,NEAR + DOSAssume CS,,"BufWrt" + ASSUME ES:NOTHING + + Assert ISDPB,,"BufWrt" + MOV AX,WORD PTR [SECPOS] + ADD AX,1 ; Set for next sector + MOV WORD PTR [SECPOS],AX ;F.C. >32mb ;AN000; + ADC WORD PTR [SECPOS+2],0 ;F.C. >32mb ;AN000; + MOV AX,WORD PTR [SECPOS+2] ;F.C. >32mb ;AN000; + CMP AX,WORD PTR [VALSEC+2] ;F.C. >32mb ;AN000; + MOV AL,1 ;F.C. >32mb ;AN000; + JA NOREAD ;F.C. >32mb ;AN000; + JB doread ;F.C. >32mb ;AN000; + MOV AX,WORD PTR [SECPOS] ;F.C. >32mb ;AN000; + CMP AX,WORD PTR [VALSEC] ; Has sector been written before? + MOV AL,1 + JA NOREAD ; Skip preread if SECPOS>VALSEC +doread: + XOR AL,AL +NOREAD: + PUSH ES + CALL BUFSEC + JC BUF_IO_FAIL + MOV DS,[DMAADD+2] +ASSUME DS:NOTHING + SHR CX,1 + JNC EVENWRT + MOVSB +EVENWRT: + REP MOVSW + POP ES + LDS BX,[CURBUF] + Assert ISBUF,,"BufWrt/EvenWrt" + + TEST [BX.buf_flags],buf_dirty ;LB. if already dirty ;AN000; + JNZ yesdirty ;LB. don't increment dirty count ;AN000; + invoke INC_DIRTY_COUNT ;LB. ;AN000; + OR [BX.buf_flags],buf_dirty +yesdirty: + LEA SI,[BX.BufInSiz] + SUB DI,SI ; Position in buffer + MOV SI,DI + MOV DI,BX + invoke PLACEBUF + Assert ISDPB,,"BufWrt/EvenWrt" + CMP SI,ES:[BP.dpb_sector_size] ; Written last byte? + JB WBUFPLACED ; No, leave buf where it is + invoke PLACEHEAD ; Make it prime candidate for chucking + ; even though it is MRU. +WBUFPLACED: + CLC + PUSH SS + POP DS + return +EndProc BUFWRT + +Break + +; Compute the next sector to read or write +; ES:BP Points to DPB + + procedure NEXTSEC,NEAR + DOSAssume CS,,"NextSec" + ASSUME ES:NOTHING + + Assert ISDPB,,"NextSec" + TEST BYTE PTR [TRANS],-1 + JZ CLRET + MOV AL,[SECCLUSPOS] + INC AL + CMP AL,ES:[BP.dpb_cluster_mask] + JBE SAVPOS + MOV BX,[CLUSNUM] + Invoke IsEOF + JAE NONEXT +;; 11/5/86 FastSeek + TEST [FastSeekflg],Fast_yes ; fastseek installed? ;AN000; + JZ do_norm2 ; no ;AN000; + PUSH [LASTPOS] ; save logical cluster # ;AN000; + POP [FSeek_logclus] ;AN000; + INC [FSeek_logclus] ; get next cluster ;AN000; + ;AN000; + TEST [FastSeekflg],FS_begin ; from R/W ;AN000; + JZ do_norm2 ; no ;AN000; +look2: ;AN000; + invoke FastSeek_Lookup ; call lookup ;AN000; + JNC clusgot ; found one ;AN000; + + CMP DI,1 ; valid drive ,e.g. C,D... ;AN000; + JNZ parfound2 ; yes, ;AN000; + AND [FastSeekflg],Fast_yes ; no more, fastseek ;AN000; + JMP SHORT do_norm2 ;AN000; +parfound2: + CALL FS_TRUNC_EOF ; check EOF ;AN000; + MOV BX,[CLUSNUM] ; don't need partially found cluster + OR [FastSeekflg],FS_insert ; prepared for cluster insertion ;AN000; + ; use the old bx ;AN000; + ;AN000; +do_norm2: + invoke UNPACK + JC NONEXT + invoke FastSeek_Insert ; call insert ;AN000; + AND [FastSeekflg],FS_no_insert ; clear insert flag ;AN000; + ;AN000; +clusgot: +;; 11/5/86 FastSeek + MOV [CLUSNUM],DI + INC [LASTPOS] + MOV AL,0 +SAVPOS: + MOV [SECCLUSPOS],AL +CLRET: + CLC + return +NONEXT: + STC + return +EndProc NEXTSEC + +Break + +; Inputs: +; BX = Physical cluster +; CX = No. of records +; DL = sector within cluster +; ES:BP = Base of drives parameters +; [NEXTADD] = transfer address +; Outputs: +; AX = No. of records remaining +; BX = Transfer address +; CX = No. or records to be transferred +; DX = Physical sector address (LOW) +; [HIGH_SECTOR] = Physical sector address (HIGH) +; DI = Next cluster +; [CLUSNUM] = Last cluster accessed +; [NEXTADD] updated +; Carry set if error (currently user FAILed to I 24) +; ES:BP unchanged. Note that segment of transfer not set. + + procedure OPTIMIZE,NEAR + DOSAssume CS,,"Optimize" + ASSUME ES:NOTHING + + Assert ISDPB,,"Optimize" + PUSH DX + PUSH BX + MOV AL,ES:[BP.dpb_cluster_mask] + INC AL ; Number of sectors per cluster + MOV AH,AL + SUB AL,DL ; AL = Number of sectors left in first cluster + MOV DX,CX + MOV CX,0 +;;; 11/5/86 FastSeek + PUSH [LASTPOS] ; save logical cluster # ;AN000; + POP [FSeek_logclus] ;AN000; + INC [FSeek_logclus] ; get next cluster ;AN000; + ;AN000; +OPTCLUS: +; AL has number of sectors available in current cluster +; AH has number of sectors available in next cluster +; BX has current physical cluster +; CX has number of sequential sectors found so far +; DX has number of sectors left to transfer +; ES:BP Points to DPB +; ES:SI has FAT pointer + + TEST [FastSeekflg],Fast_yes ; fastseek installed? ;AN000; + JZ do_norm3 ; no ;AN000; + TEST [FastSeekflg],FS_begin ; from R/W ;AN000; + JZ do_norm3 ; no ;AN000; + TEST [FastSeekflg],FS_insert ; is in insert mode ? ;AN000; + JNZ do_norm3 ; yes ;AN000; + invoke FastSeek_Lookup ; call lookup ;AN000; + JNC clusgot2 ; found one ;AN000; + + CMP DI,1 ; valid drive ,e.g. C,D... ;AN000; + JNZ par_found3 ; yes, ;AN000; + AND [FastSeekflg],Fast_yes ; no more, fastseek ;AN000; + JMP SHORT do_norm3 ;AN000; +par_found3: + PUSH BX + CALL FS_TRUNC_EOF ; file entry not existing ;AN000; + POP BX ;AN000; + OR [FastSeekflg],FS_insert ; prepare for insertion ;AN000; + ; use old bx ;AN000; +do_norm3: + invoke UNPACK + JC OP_ERR +clusgot2: + invoke FastSeek_Insert ; call insert ;AN000; + INC [FSeek_logclus] ; insert to next position ;AN000; +;;; 11/5/86 FastSeek ;AN000; + ADD CL,AL + ADC CH,0 + CMP CX,DX + JAE BLKDON + MOV AL,AH + INC BX + CMP DI,BX + JZ OPTCLUS + DEC BX +FINCLUS: + MOV [CLUSNUM],BX ; Last cluster accessed + SUB DX,CX ; Number of sectors still needed + PUSH DX + MOV AX,CX + MUL ES:[BP.dpb_sector_size] ; Number of sectors times sector size + MOV SI,[NEXTADD] + ADD AX,SI ; Adjust by size of transfer + MOV [NEXTADD],AX + POP AX ; Number of sectors still needed + POP DX ; Starting cluster + SUB BX,DX ; Number of new clusters accessed + ADD [LASTPOS],BX + POP BX ; BL = sector postion within cluster + invoke FIGREC + MOV BX,SI + AND [FastSeekflg],FS_no_insert ; clear insert flag + CLC + return + +OP_ERR: + ADD SP,4 + AND [FastSeekflg],FS_no_insert ; clear insert flag + STC + return + +BLKDON: + SUB CX,DX ; Number of sectors in cluster we don't want + SUB AH,CL ; Number of sectors in cluster we accepted + DEC AH ; Adjust to mean position within cluster + MOV [SECCLUSPOS],AH + MOV CX,DX ; Anyway, make the total equal to the request + JMP SHORT FINCLUS +EndProc OPTIMIZE + +Break + +; Inputs: +; DX = Physical cluster number +; BL = Sector postion within cluster +; ES:BP = Base of drive parameters +; Outputs: +; DX = physical sector number (LOW) +; [HIGH_SECTOR] Physical sector address (HIGH) +; No other registers affected. + + procedure FIGREC,NEAR +ASSUME DS:NOTHING,ES:NOTHING + + Assert ISDPB,,"FigRec" + PUSH CX + MOV CL,ES:[BP.dpb_cluster_shift] + DEC DX + DEC DX + MOV [HIGH_SECTOR],0 ;F.C. >32mb + OR CL,CL ;F.C. >32mb + JZ noshift ;F.C. >32mb + XOR CH,CH ;F.C. >32mb +rotleft: ;F.C. >32mb + CLC ;F.C. >32mb + RCL DX,1 ;F.C. >32mb + RCL [HIGH_SECTOR],1 ;F.C. >32mb + LOOP rotleft ;F.C. >32mb +noshift: + +; SHL DX,CL + OR DL,BL + ADD DX,ES:[BP.dpb_first_sector] + ADC [HIGH_SECTOR],0 ;F.C. >32mb + POP CX + return +EndProc FIGREC + +Break + +;*** ALLOCATE - Allocate Disk Space +; +; ALLOCATE is called to allocate disk clusters. The new clusters are +; FAT-chained onto the end of the existing file. +; +; The DPB contains the cluster # of the last free cluster allocated +; (dpb_next_free). We start at this cluster and scan towards higher +; numbered clusters, looking for the necessary free blocks. +; +; Once again, fancy terminology gets in the way of corrct coding. When +; using next_free, start scanning AT THAT POINT and not the one following it. +; This fixes the boundary condition bug when only free = next_free = 2. +; +; If we get to the end of the disk without satisfaction: +; +; if (dpb_next_free == 2) then we've scanned the whole disk. +; return (insufficient_disk_space) +; ELSE +; dpb_next_free = 2; start scan over from the beginning. +; +; Note that there is no multitasking interlock. There is no race when +; examining the entrys in an in-core FAT block since there will be no +; context switch. When UNPACK context switches while waiting for a FAT read +; we are done with any in-core FAT blocks, so again there is no race. The +; only special concern is that V2 and V3 MSDOS left the last allocated +; cluster as "00"; marking it EOF only when the entire alloc request was +; satisfied. We can't allow another activation to think this cluster is +; free, so we give it a special temporary mark to show that it is, indeed, +; allocated. +; +; Note that when we run out of space this algorithem will scan from +; dpb_next_free to the end, then scan from cluster 2 through the end, +; redundantly scanning the later part of the disk. This only happens when +; we run out of space, so sue me. +; +;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; +; C A V E A T P A T T E R S O N ; +; ; +; The use of FATBYT and RESTFATBYT is somewhat mysterious. Here is the +; explanation: +; +; In the NUL file case (sf_firclus currently 0) ALLOCATE is called with +; entry BX = 0. What needs to be done in this case is to stuff the cluster +; number of the first cluster allocated in sf_firclus when the ALLOCATE is +; complete. THIS VALUE IS SAVED TEMPORARILY IN CLUSTER 0, HENCE THE CURRENT +; VALUE IN CLUSTER 0 MUST BE SAVED AND RESTORED. This is a side effect of +; the fact that PACK and UNPACK don't treat requests for clusters 0 and 1 as +; errors. This "stuff" is done by the call to PACK which is right before +; the +; LOOP findfre ; alloc more if needed +; instruction when the first cluster is allocated to the nul file. The +; value is recalled from cluster 0 and stored at sf_firclus at ads4: +; +; This method is obviously useless (because it is non-reentrant) for +; multitasking, and will have to be changed. Storing the required value on +; the stack is recommended. Setting sf_firclus at the PACK of cluster 0 +; (instead of actually doing the PACK) is BAD because it doesn't handle +; problems with INT 24 well. +; +; C A V E A T P A T T E R S O N ; +;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----; +; ; +; ENTRY BX = Last cluster of file (0 if null file) +; CX = No. of clusters to allocate +; ES:BP = Base of drive parameters +; [THISSFT] = Points to SFT +; +; EXIT 'C' set if insufficient space +; [FAILERR] can be tested to see the reason for failure +; CX = max. no. of clusters that could be added to file +; 'C' clear if space allocated +; BX = First cluster allocated +; FAT is fully updated +; sf_FIRCLUS field of SFT set if file was null +; +; USES ALL but SI, BP + + PROCEDURE ALLOCATE,NEAR + + DOSAssume CS,,"Allocate" + ASSUME ES:NOTHING + + Assert ISDPB,,"Allocate" + PUSH BX ; save (bx) + XOR BX,BX + invoke UNPACK + MOV [FATBYT],DI ; save correct cluster 0 value + POP BX + retc ; abort if error [INTERR?] + + PUSH CX + PUSH BX + + MOV DX,BX + Assert ISDPB,,"Allocate/Unpack" + mov bx,es:[bp.dpb_next_free] + cmp bx,2 + ja findfre + +; couldn't find enough free space beyond dpb_next_free, or dpb_next_free is +; <2 or >dpb_max_clus. Reset it and restart the scan + +ads1: + Assert ISDPB,,"Alloc/ads1" + mov es:[bp.dpb_next_free],2 + mov bx,1 ; Counter next instruction so first + ; cluster examined is 2 + +; Scanning both forwards and backwards for a free cluster +; +; (BX) = forwards scan pointer +; (CX) = clusters remaining to be allocated +; (DX) = current last cluster in file +; (TOS) = last cluster of file + +FINDFRE: + INC BX + Assert ISDPB,,"Alloc/findfre" + CMP BX,ES:[BP.dpb_max_cluster] + JBE aupk + jmp ads7 ; at end of disk +aupk: + invoke UNPACK ; check out this cluster + jc ads4 ; FAT error [INTERR?] + jnz findfre ; not free, keep on truckin + +; Have found a free cluster. Chain it to the file +; +; (BX) = found free cluster # +; (DX) = current last cluster in file + + mov es:[bp.dpb_next_free],bx ; next time start search here + xchg ax,dx ; save (dx) in ax + mov dx,1 ; mark this free guy as "1" + invoke PACK ; set special "temporary" mark + jc ads4 ; FAT error [INTERR?] + CMP ES:[BP.dpb_free_cnt],-1 ; Free count valid? + JZ NO_ALLOC ; No + DEC ES:[BP.dpb_free_cnt] ; Reduce free count by 1 +NO_ALLOC: + xchg ax,dx ; (dx) = current last cluster in file + XCHG BX,DX + MOV AX,DX + invoke PACK ; link free cluster onto file + ; CAVEAT.. On Nul file, first pass stuffs + ; cluster 0 with FIRCLUS value. + jc ads4 ; FAT error [INTERR?] + xchg BX,AX ; (BX) = last one we looked at + mov dx,bx ; (dx) = current end of file + LOOP findfre ; alloc more if needed + +; We've successfully extended the file. Clean up and exit +; +; (BX) = last cluster in file + + MOV DX,0FFFFH + invoke PACK ; mark last cluster EOF + +; Note that FAT errors jump here to clean the stack and exit. this saves us +; 2 whole bytes. Hope its worth it... +; +; 'C' set iff error +; calling (BX) and (CX) pushed on stack + +ads4: POP BX + POP CX ; Don't need this stuff since we're successful + retc + invoke UNPACK ; Get first cluster allocated for return + ; CAVEAT... In nul file case, UNPACKs cluster 0. + retc + invoke RESTFATBYT ; Restore correct cluster 0 value + retc + XCHG BX,DI ; (DI) = last cluster in file upon our entry + OR DI,DI ; clear 'C' + retnz ; we were extending an existing file + +; We were doing the first allocation for a new file. Update the SFT cluster +; info +;; Extended Attributes +; TEST [XA_condition],XA_No_SFT ;FT. don't update SFT when from ;AN000; +; JZ dofastk ;FT. GetSet_XA ;AN000; +; AND [XA_condition],not XA_No_SFT ;FT. clear the bit ;AN000; +; CLC ;FT. ;AN000; +; ret ;FT. ;AN000; +;; 11/6/86 FastSeek +dofastk: + PUSH DX + MOV DL,ES:[BP.dpb_drive] ; get drive # + + PUSH ES + LES DI,[THISSFT] + Assert ISSFT,,"Allocate/ads4" + MOV ES:[DI.sf_firclus],BX + MOV ES:[DI.sf_lstclus],BX + + TEST [FastSeekflg],Fast_yes ; fastseek installed + JZ do_norm5 ; no + TEST [FastSeekflg],FS_begin ; do fastseek + JZ do_norm5 ; no + PUSH CX + MOV CX,BX ; set up firclus # + MOV [FSeek_firclus],BX ; update firclus varible + invoke FastSeek_Open ; create this file entry + POP CX +do_norm5: + POP ES +;; 11/6/86 FastSeek + POP DX + return + + +;** we're at the end of the disk, and not satisfied. See if we've scanned ALL +; of the disk... + +ads7: cmp es:[bp.dpb_next_free],2 +if not debug + jz tmplab2 ; + jmp ads1 ; start scan from front of disk +tmplab2: +else + jz tmplab + jmp ads1 +tmplab: +endif + +; Sorry, we've gone over the whole disk, with insufficient luck. Lets give +; the space back to the free list and tell the caller how much he could have +; had. We have to make sure we remove the "special mark" we put on the last +; cluster we were able to allocate, so it doesn't become orphaned. +; +; (CX) = clusters remaining to be allocated +; (TOS) = last cluster of file (before call to ALLOCATE) +; (TOS+1) = # of clusters wanted to allocate + + + POP BX ; (BX) = last cluster of file + MOV DX,0FFFFH + invoke RELBLKS ; give back any clusters just alloced + POP AX ; No. of clusters requested + ; Don't "retc". We are setting Carry anyway, + ; Alloc failed, so proceed with return CX + ; setup. + SUB AX,CX ; AX=No. of clusters allocated + invoke RESTFATBYT ; Don't "retc". We are setting Carry anyway, + ; Alloc failed. +; fmt <>,<>,<"$p: disk full in allocate\n"> + MOV [DISK_FULL],1 ;MS. indicating disk full + STC + return + +EndProc ALLOCATE + +; SEE ALLOCATE CAVEAT +; Carry set if error (currently user FAILed to I 24) + + procedure RESTFATBYT,NEAR + DOSAssume CS,,"RestFATByt" + ASSUME ES:NOTHING + + PUSH BX + PUSH DX + PUSH DI + XOR BX,BX + MOV DX,[FATBYT] + invoke PACK + POP DI + POP DX + POP BX + return +EndProc RESTFATBYT + +Break + +; Inputs: +; BX = Cluster in file +; ES:BP = Base of drive parameters +; Function: +; Frees cluster chain starting with [BX] +; Carry set if error (currently user FAILed to I 24) +; AX,BX,DX,DI all destroyed. Other registers unchanged. + + procedure RELEASE,NEAR + DOSAssume CS,,"Release" + ASSUME ES:NOTHING + + XOR DX,DX +entry RELBLKS + DOSAssume CS,,"RelBlks" + Assert ISDPB,,"RelBlks" + +; Enter here with DX=0FFFFH to put an end-of-file mark in the first cluster +; and free the rest in the chain. + + invoke UNPACK + retc + retz + MOV AX,DI + PUSH DX + invoke PACK + POP DX + retc + OR DX,DX + JNZ NO_DEALLOC ; Was putting EOF mark + CMP ES:[BP.dpb_free_cnt],-1 ; Free count valid? + JZ NO_DEALLOC ; No + INC ES:[BP.dpb_free_cnt] ; Increase free count by 1 +NO_DEALLOC: + MOV BX,AX + dec ax ; check for "1" + retz ; is last cluster of incomplete chain + Invoke IsEOF + JB RELEASE ; Carry clear if JMP not taken +ret12: return +EndProc RELEASE + +Break + +; Inputs: +; ES:BP Points to DPB +; BX = Cluster in a file +; DS = CS +; Outputs: +; BX = Last cluster in the file +; Carry set if error (currently user FAILed to I 24) +; DI destroyed. No other registers affected. + + procedure GETEOF,NEAR + DOSAssume CS,,"GetEOF" + ASSUME ES:NOTHING + + Assert ISDPB,,"GetEof" + invoke UNPACK + retc + PUSH BX + MOV BX,DI + Invoke IsEOF + POP BX + JAE RET12 ; Carry clear if jmp + MOV BX,DI + JMP GETEOF +EndProc GETEOF + +Break + +; Inputs: +; ES:BP Points to DPB +; BX = Cluster in a file +; Functions: if BX=EOF then truncate it from Fastseek Cache +; Outputs: +; carry set: not EOF +; carry clear: EOF and do truncate + + procedure FS_TRUNC_EOF,NEAR + ASSUME ES:NOTHING,DS:NOTHING + + MOV BX,DI ; get beginning physical# ;AN000; + invoke IsEOF ; is EOF ;AN000; + JB noteof2 ; no ;AN000; + PUSH [FSeek_logclus] ; ;AN000; + PUSH [FSeek_logsave] ; logclus=logsave ;AN000; + POP [FSeek_logclus] ; delete EOF ;AN000; + invoke FastSeek_Truncate ; ;AN000; + POP [FSeek_logclus] ; redo the look up ;AN000; + CLC ;AN000; +noteof2: ;AN000; + return ;AN000; +EndProc FS_TRUNC_EOF ;AN000; + +CODE ENDS + END + \ No newline at end of file diff --git a/v4.0/src/DOS/SEARCH.ASM b/v4.0/src/DOS/SEARCH.ASM new file mode 100644 index 0000000..1f23942 --- /dev/null +++ b/v4.0/src/DOS/SEARCH.ASM @@ -0,0 +1,346 @@ +; SCCSID = @(#)search.asm 1.1 85/04/10 +TITLE SEARCH - Directory scan system calls +NAME SEARCH + +; +; +; Directory search system calls. These will be passed direct text of the +; pathname from the user. They will need to be passed through the macro +; expander prior to being sent through the low-level stuff. I/O specs are +; defined in DISPATCH. The system calls are: +; +; +; $Dir_Search_First written +; $Dir_Search_Next written +; $Find_First written +; $Find_Next written +; PackName written +; +; Modification history: +; +; Created: ARR 4 April 1983 +; + +.xlist +; +; get the appropriate segment definitions +; +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGroup,CS:DOSGroup + +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +INCLUDE fastopen.inc +INCLUDE fastxxxx.inc +.cref +.list + + i_need SEARCHBUF,53 + i_need SATTRIB,BYTE + I_Need OpenBuf,128 + I_need DMAAdd,DWORD + I_need THISFCB,DWORD + I_need CurDrv,BYTE + I_need EXTFCB,BYTE + I_need Fastopenflg,BYTE + I_need DOS34_FLAG,WORD + +; Inputs: +; DS:DX Points to unopenned FCB +; Function: +; Directory is searched for first matching entry and the directory +; entry is loaded at the disk transfer address +; Returns: +; AL = -1 if no entries matched, otherwise 0 + + procedure $DIR_SEARCH_FIRST,NEAR +ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup + + MOV WORD PTR [THISFCB],DX + MOV WORD PTR [THISFCB+2],DS + MOV SI,DX + CMP BYTE PTR [SI],0FFH + JNZ NORMFCB4 + ADD SI,7 ; Point to drive select byte +NORMFCB4: + SaveReg <[SI]> ; Save original drive byte for later + Context ES ; get es to address DOSGroup + MOV DI,OFFSET DOSGroup:OpenBuf ; appropriate buffer + invoke TransFCB ; convert the FCB, set SATTRIB EXTFCB + JNC SearchIt ; no error, go and look + RestoreReg ; Clean stack +; +; Error code is in AX +; + transfer FCB_Ret_Err ; error + +SearchIt: + Context DS ; get ready for search + SaveReg <, > + MOV WORD PTR [DMAAdd],OFFSET DOSGroup:SEARCHBUF + MOV WORD PTR [DMAAdd+2],DS + invoke GET_FAST_SEARCH ; search + RestoreReg <, > + JNC SearchSet ; no error, transfer info + RestoreReg ; Clean stack +; +; Error code is in AX +; + transfer FCB_Ret_Err + +; +; The search was successful (or the search-next). We store the information +; into the user's FCB for continuation. +; +SearchSet: + MOV SI,OFFSET DOSGroup:SEARCHBUF + LES DI,[THISFCB] ; point to the FCB + TEST [EXTFCB],0FFH ; + JZ NORMFCB1 + ADD DI,7 ; Point past the extension +NORMFCB1: + RestoreReg ; Get original drive byte + OR BL,BL + JNZ SearchDrv + MOV BL,[CurDrv] + INC BL +SearchDrv: + LODSB ; Get correct search contin drive byte + XCHG AL,BL ; Search byte to BL, user byte to AL + INC DI +; STOSB ; Store the correct "user" drive byte + ; at the start of the search info + MOV CX,20/2 + REP MOVSW ; Rest of search cont info, SI -> entry + XCHG AL,BL ; User drive byte back to BL, search + ; byte to AL + STOSB ; Search contin drive byte at end of + ; contin info + LES DI,[DMAAdd] + TEST [EXTFCB],0FFH + JZ NORMFCB2 + MOV AL,0FFH + STOSB + INC AL + MOV CX,5 + REP STOSB + MOV AL,[SATTRIB] + STOSB +NORMFCB2: + MOV AL,BL ; User Drive byte + STOSB + IF DBCS ;AN000; + MOVSW ; 2/13/KK ;AN000; + CMP BYTE PTR ES:[DI-2],5 ; 2/13/KK ;AN000; + JNZ NOTKTRAN ; 2/13/KK ;AN000; + MOV BYTE PTR ES:[DI-2],0E5H ; 2/13/KK ;AN000; +NOTKTRAN: ; 2/13/KK ;AN000; + MOV CX,15 ; 2/13/KK ;AN000; + ELSE ;AN000; + MOV CX,16 ; 32 / 2 words of dir entry ;AN000; + ENDIF ;AN000; + REP MOVSW + transfer FCB_Ret_OK + +EndProc $DIR_SEARCH_FIRST + +; Inputs: +; DS:DX points to unopenned FCB returned by $DIR_SEARCH_FIRST +; Function: +; Directory is searched for the next matching entry and the directory +; entry is loaded at the disk transfer address +; Returns: +; AL = -1 if no entries matched, otherwise 0 + + procedure $DIR_SEARCH_NEXT,NEAR +ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup + + MOV WORD PTR [THISFCB],DX + MOV WORD PTR [THISFCB+2],DS + MOV [SATTRIB],0 + MOV [EXTFCB],0 + Context ES + MOV DI,OFFSET DOSGroup:SEARCHBUF + MOV SI,DX + CMP BYTE PTR [SI],0FFH + JNZ NORMFCB6 + ADD SI,6 + LODSB + MOV [SATTRIB],AL + DEC [EXTFCB] +NORMFCB6: + LODSB ; Get original user drive byte + SaveReg ; Put it on stack + MOV AL,[SI+20] ; Get correct search contin drive byte + STOSB ; Put in correct place + MOV CX,20/2 + REP MOVSW ; Transfer in rest of search contin info + Context DS + SaveReg <, > + MOV WORD PTR [DMAAdd],OFFSET DOSGroup:SEARCHBUF + MOV WORD PTR [DMAAdd+2],DS + invoke DOS_SEARCH_NEXT ; Find it + RestoreReg <, > + JC SearchNoMore + JMP SearchSet ; Ok set return + +SearchNoMore: + LES DI,[THISFCB] + TEST [EXTFCB],0FFH + JZ NORMFCB8 + ADD DI,7 ; Point past the extension +NORMFCB8: + RestoreReg ; Get original drive byte + MOV ES:[DI],BL ; Store the correct "user" drive byte + ; at the right spot +; +; error code is in AX +; + transfer FCB_Ret_Err + +EndProc $DIR_SEARCH_NEXT + +; Assembler usage: +; MOV AH, FindFirst +; LDS DX, name +; MOV CX, attr +; INT 21h +; ; DMA address has datablock +; +; Error Returns: +; AX = error_path_not_found +; = error_no_more_files + + procedure $FIND_FIRST,NEAR +ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup + + MOV SI,DX ; get name in appropriate place + MOV [SATTRIB],CL ; Search attribute to correct loc + MOV DI,OFFSET DOSGroup:OpenBuf ; appropriate buffer + invoke TransPathSet ; convert the path + JNC Find_it ; no error, go and look +FindError: + error error_path_not_found ; error and map into one. +Find_it: + Context DS + SaveReg <, > + MOV WORD PTR [DMAAdd],OFFSET DOSGroup:SEARCHBUF + MOV WORD PTR [DMAAdd+2],DS + invoke GET_FAST_SEARCH ; search + RestoreReg <, > + JNC FindSet ; no error, transfer info + transfer Sys_Ret_Err + +FindSet: + MOV SI,OFFSET DOSGroup:SEARCHBUF + LES DI,[DMAAdd] + MOV CX,21 + REP MOVSB + PUSH SI ; Save pointer to start of entry + MOV AL,[SI.dir_attr] + STOSB + ADD SI,dir_time + MOVSW ; dir_time + MOVSW ; dir_date + INC SI + INC SI ; Skip dir_first + MOVSW ; dir_size (2 words) + MOVSW + POP SI ; Point back to dir_name + IF DBCS ;AN000; + PUSH DI ; XXXX save dest name 2/13/KK ;AN000; + CALL PackName ;AN000; + POP DI ; XXXX Recover dest name 2/13/KK ;AN000; + CMP BYTE PTR ES:[DI],05H ; XXXX Need fix? 2/13/KK ;AN000; + JNZ FNXXX ; XXXX No 2/13/KK ;AN000; + MOV BYTE PTR ES:[DI],0E5H ; XXXX Yes, Fix 2/13/KK ;AN000; +FNXXX: ; 2/13/KK ;AN000; + ELSE ;AN000; + CALL PackName + ENDIF + transfer Sys_Ret_OK ; bye with no errors +EndProc $FIND_FIRST + + procedure $FIND_NEXT,NEAR +ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup + +; Assembler usage: +; ; dma points at area returned by find_first +; MOV AH, findnext +; INT 21h +; ; next entry is at dma +; +; Error Returns: +; AX = error_no_more_files + + Context ES + MOV DI,OFFSET DOSGroup:SEARCHBUF + LDS SI,[DMAAdd] + MOV CX,21 + REP MOVSB ; Put the search continuation info + ; in the right place + Context DS ; get ready for search + SaveReg <, > + MOV WORD PTR [DMAAdd],OFFSET DOSGroup:SEARCHBUF + MOV WORD PTR [DMAAdd+2],DS + invoke DOS_SEARCH_NEXT ; Find it + RestoreReg <, > + JNC FindSet ; No error, set info + transfer Sys_Ret_Err + +EndProc $FIND_NEXT + +Break +; +; PackName - transfer a file name from DS:SI to ES:DI and convert it to +; the ASCIZ format. +; +; Input: DS:SI points to an 11 character FCB or dir entry name +; ES:DI points to a destination area (13 bytes) +; Output: Above pointers advanced +; Registers modified: SI,DI,CX,AL + Procedure PackName,NEAR + ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup + MOV CX,8 ; Pack the name + REP MOVSB ; Move all of it +main_kill_tail: + CMP BYTE PTR ES:[DI-1]," " + JNZ find_check_dot + DEC DI ; Back up over trailing space + INC CX + CMP CX,8 + JB main_kill_tail +find_check_dot: + CMP WORD PTR [SI],(" " SHL 8) OR " " + JNZ got_ext ; Some chars in extension + CMP BYTE PTR [SI+2]," " + JZ find_done ; No extension +got_ext: + MOV AL,"." + STOSB + MOV CX,3 + REP MOVSB +ext_kill_tail: + CMP BYTE PTR ES:[DI-1]," " + JNZ find_done + DEC DI ; Back up over trailing space + JMP ext_kill_tail +find_done: + XOR AX,AX + STOSB ; NUL terminate + return +EndProc PackName + + procedure GET_FAST_SEARCH,NEAR + ASSUME DS:NOTHING,ES:NOTHING + + OR [DOS34_FLAG],SEARCH_FASTOPEN ;FO.trigger fastopen ;AN000; + invoke DOS_SEARCH_FIRST + return + +EndProc GET_FAST_SEARCH +CODE ENDS +END diff --git a/v4.0/src/DOS/SEGCHECK.ASM b/v4.0/src/DOS/SEGCHECK.ASM new file mode 100644 index 0000000..992eac2 --- /dev/null +++ b/v4.0/src/DOS/SEGCHECK.ASM @@ -0,0 +1,288 @@ +; SCCSID = @(#)segcheck.asm 1.2 85/07/24 +TITLE SegCheck - internal consistency check +NAME SegCheck + +.xlist +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC + +ShareF = FALSE + +IF NOT SHAREF +include dosseg.asm +ENDIF +.list + +AsmVars + +DEBUG = FALSE + +IF NOT SHAREF +CODE SEGMENT BYTE PUBLIC 'CODE' +ASSUME CS:DOSGroup +ELSE +SHARE SEGMENT BYTE PUBLIC 'SHARE' +ASSUME CS:SHARE +ENDIF + +DEBUG = FALSE + +BREAK + +Off Macro reg,var +IF SHAREF + mov reg,offset var +else + mov reg,offset DOSGroup:var +endif +endm + +zfmt MACRO fmts,args +local a,b + PUSHF + PUSH AX + PUSH BP + MOV BP,SP +If (not sharef) and (not redirector) +Table segment +a db fmts,0 +Table ends + MOV AX,OFFSET DOSGROUP:a +else + jmp short b +a db fmts,0 +if sharef +b: mov ax,offset share:a +else +b: mov ax,offset netwrk:a +endif +endif + PUSH AX +cargs = 2 +IRP item, +IFIDN , + MOV AX,[BP+2] +ELSE + MOV AX,item +ENDIF + PUSH AX +cargs = cargs + 2 +ENDM + invoke PFMT + ADD SP,Cargs + POP BP + POP AX + POPF +ENDM + +segFrame Struc +segbp DW ? +segip DW ? +segmes dw ? +segtemp DW ? +segFrame ENDS +; +; SegCheck - assure that segments are correctly set up +; +; Inputs: top of stack points to: +; 2-byte jump +; byte flags 04h is ES 02h is DS 01 is CS/SS +; offset asciz message +; +; Outputs: message to screen (via INT 29h) +; Nothing modified (flags too) + +Procedure SegCheck,NEAR + ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + SaveReg + MOV BP,SP ; set up addressing + PUSHF + SaveReg + MOV AL,BYTE PTR [BP].segtemp; get flags + MOV CX,SS + TEST AL,1 ; shall we use CS or SS? + JZ SegUseSS ; use SS + MOV CX,CS ; use CS instead +SegUseSS: + TEST AL,2 ; do we check DS? + JZ SegTestES ; no, go check ES + MOV DX,DS + CMP CX,DX + JZ SegTestES ; DS is valid, go check ES + MOV AX,[BP].segmes + zfmt <"Assumed DS invalid $s\n">, +SegTestES: + TEST AL,4 ; do we check ES? + JZ SegTestDone ; no, all done + MOV DX,ES + CMP CX,DX + JZ SegTestDone ; ES is valid, all done + MOV AX,[BP].segmes + zfmt <"Assumed ES invalid $s\n">, +SegTestDone: + RestoreReg + POPF + RestoreReg + ret 4 ; release message, temp +EndProc SegCheck + + +IF NOT SHAREF +I_need DPBHead,DWORD +I_need BuffHead,DWORD +I_need sftFCB,DWORD +I_need AuxStack,BYTE +I_need IOStack,BYTE +I_need renbuf,byte +I_need CurrentPDB,WORD +I_need User_In_AX,WORD + +extrn ECritDisk:NEAR + +CritNOP label byte + RET + +AstFrame STRUC +Astbp dw ? +Astip dw ? +Astmes dw ? +Astarg dd ? +AstFrame ENDS + +Public SGCHK001S,SGCHK001E +SGCHK001S label byte +DPBMes DB "DPB assertion failed: ",0 +BUFMes DB "BUF assertion failed: ",0 +SFTMes DB "SFT assertion failed: ",0 +BlankSp DB " ",0 +Colon DB ":",0 + +Msg DW ? + +SGCHK001E label byte + +Table segment + Extrn SectPDB:WORD, SectRef:WORD +Table ends + +; DPBCheck - validate a supposed DPB pointer +; Inputs: Pushed arguments +; Outputs: Message to screen +; Registers modified: none + +Procedure DPBCheck,NEAR + MOV Msg,OFFSET DOSGroup:DPBMes + SaveReg + MOV BP,SP + PUSHF + SaveReg + LES DI,DPBHead + LDS SI,[BP].Astarg +DPBLoop:CMP DI,-1 + JZ DPBNotFound + invoke PointComp + JZ DPBRet + LES DI,ES:[DI.dpb_next_dpb] + JMP DPBLoop +DPBNotFound: + MOV AX,[BP].Astmes + zfmt <"$s$x:$x $s\n">, + CLI +a: JMP a ; slam the door. +DPBRet: RestoreReg ; Done: + POPF + RestoreReg + RET 6 +EndProc DPBCheck + +; SFTCheck - validate a supposed SFT pointer +; Inputs: Pushed arguments +; Outputs: Message to screen +; Registers modified: none + +Procedure SFTCheck,NEAR + MOV Msg,OFFSET DOSGroup:SFTMes + SaveReg + MOV BP,SP + PUSHF + SaveReg + LDS SI,[BP].Astarg + XOR BX,BX ; i = 0; +SFTLoop: + SaveReg + invoke SFFromSFN ; while ((d=SF(i)) != NULL) + RestoreReg + JC Sft1 + invoke PointComp + JZ DPBRet ; goto Done; +SFTNext:INC BX ; else + JMP SFTLoop ; i++; +SFT1: LES DI,sftFCB + MOV BX,ES:[DI.sfCount] + LEA DI,[DI.sfTable] +SFT2: + invoke PointComp +DPBRETJ:JZ DPBRet + ADD DI,SIZE sf_entry + DEC BX + JNZ SFT2 +; +; The SFT is not in the allocated tables. See if it is one of the static +; areas. +; + Context ES + MOV DI,OFFSET DOSGROUP:AUXSTACK - SIZE SF_ENTRY + Invoke PointComp + JZ DPBRet + MOV DI,OFFSET DOSGROUP:RenBuf + Invoke PointComp + JZ DPBRetj +DPBNotFoundJ: + JMP DPBNotFound +EndProc SFTCheck + +; BUFCheck - validate a supposed BUF pointer +; Inputs: Pushed arguments +; Outputs: Message to screen +; Registers modified: none + +Procedure BUFCheck,NEAR + MOV Msg,OFFSET DOSGroup:BUFMes + SaveReg + MOV BP,SP + PUSHF + SaveReg +; +; CheckDisk - make sure that we are in the disk critical section... +; + MOV AL,BYTE PTR ECritDisk + CMP AL,CritNOP + JZ CheckDone + MOV AX,CurrentPDB + CMP SectPDB + 2 * critDisk,AX + MOV AX,[BP].astmes + JZ CheckRef + zfmt <"$p: $x $s critDisk owned by $x\n">, +CheckRef: + CMP SectRef + 2 * critDisk,0 + JNZ CheckDone + zfmt <"$p: $x $s critDisk ref count is 0\n">, +CheckDone: + + LDS SI,[BP].Astarg + LES DI,BUFFHead +BUFLoop:CMP DI,-1 + JZ DPBNotFoundJ + invoke PointComp + JNZ BufNext + JMP DPBRet +BufNext: + LES DI,ES:[DI.buf_link] + JMP BUFLoop +EndProc BUFCheck + +CODE ENDS +ELSE +SHARE ENDS +ENDIF +END diff --git a/v4.0/src/DOS/SHARE.ASM b/v4.0/src/DOS/SHARE.ASM new file mode 100644 index 0000000..ded4cd7 --- /dev/null +++ b/v4.0/src/DOS/SHARE.ASM @@ -0,0 +1,151 @@ +; SCCSID = @(#)share.asm 1.1 85/04/10 +TITLE SHARING ROUTINES - Routines for file Sharing +NAME SHARE + +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xlist +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +.cref +.list + +AsmVars + +Installed = True + + i_need THISDPB,DWORD + i_need EXTERR,WORD + i_need ReadOp,BYTE + i_need ThisSFT,DWORD + i_need ALLOWED,BYTE + I_need RetryCount,WORD + i_need JShare,DWORD + +; Inputs: +; [THISSFT] Points to filled in local file/device SFT for new +; instance of file sf_mode ALWAYS has mode (even on FCB SFTs) +; [WFP_START] has full path of name +; [USER_ID] Set +; [PROC_ID] Set +; Function: +; Check for sharing violations on local file/device access +; Outputs: +; Carry clear +; Sharing approved +; Carry set +; A sharing violation detected +; AX is error code +; USES ALL but DS + + procedure SHARE_CHECK,NEAR + DOSAssume CS,,"Share_Check" + ASSUME ES:NOTHING + +if installed + call JShare + 1 * 4 +else + Call MFT_Enter +endif + return + +EndProc SHARE_CHECK + +; Inputs: +; [THISDPB] Set +; AX has error code +; Function: +; Handle Sharing errors +; Outputs: +; Carry set if user says FAIL, causes error_sharing_violation +; Carry clear if user wants a retry +; +; DS, ES, DI preserved, others destroyed + + procedure SHARE_VIOLATION,NEAR + DOSAssume CS,,"Share_Violation" + ASSUME ES:NOTHING + + PUSH DS + PUSH ES + PUSH DI + MOV [READOP],0 ; All share errors are reading + MOV [ALLOWED],allowed_FAIL + allowed_RETRY + LES BP,[THISDPB] + MOV DI,1 ; Fake some registers + MOV CX,DI + MOV DX,ES:[BP.dpb_dir_sector] + invoke HARDERR + POP DI + POP ES + POP DS + CMP AL,1 + retz ; 1 = retry, carry clear + STC + return + +EndProc SHARE_VIOLATION + +; ShareEnd - terminate sharing info on a particular SFT/UID/PID. This does +; NOT perform a close, it merely asserts that the sharing information +; for the SFT/UID/PID may be safely released. +; +; Inputs: ES:DI points to an SFT +; Outputs: None +; Registers modified: all except DS,ES,DI + + procedure ShareEnd,Near + DOSAssume CS,,"ShareEnd" + ASSUME ES:NOTHING + +if installed + Call JShare + 2 * 4 +else + Call MFTClose +endif + return + +EndProc ShareEnd + +break + +; +; ShareEnter - perform a retried entry of a nodde into the sharing set. If +; the max number of retries is exceeded, we notify the user via int 24. +; +; Inputs: ThisSFT points to the SFT +; WFP_Start points to the WFP +; Outputs: Carry clear => successful entry +; Carry set => failed system call +; Registers modified: all + +Procedure ShareEnter,NEAR + DOSAssume CS,,"ShareEnter" + assume es:nothing + + SaveReg +retry: + mov cx,RetryCount +attempt: + les di,ThisSFT ; grab sft + XOR AX,AX + MOV ES:[DI.sf_MFT],AX ; indicate free SFT + SaveReg + call Share_Check ; attempt to enter into the sharing set + RestoreReg + jnc done ; success, let the user see this + invoke Idle ; wait a while + loop attempt ; go back for another attempt + call Share_violation ; signal the problem to the user + jnc retry ; user said to retry, go do it +done: + RestoreReg + return +EndProc ShareEnter + +CODE ENDS + END diff --git a/v4.0/src/DOS/SHRPRINT.ASM b/v4.0/src/DOS/SHRPRINT.ASM new file mode 100644 index 0000000..6854eca --- /dev/null +++ b/v4.0/src/DOS/SHRPRINT.ASM @@ -0,0 +1,35 @@ +; SCCSID = @(#)shrprint.asm 1.1 85/04/10 +TITLE SHRPRINT - PRINTF at SHARE level +NAME SHRPRINT +; +; +; Modification history: +; +; Created: MZ 16 June 1984 +; + +.xlist +; +; get the appropriate segment definitions +; +include dosseg.asm + +Share SEGMENT PARA PUBLIC 'SHARE' + ASSUME SS:DOSGROUP,CS:SHARE + +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +.cref +.list +.sall + + I_Need Proc_ID,WORD + I_Need User_ID,WORD + +BREAK + +include print.asm + +SHARE ENDS +END diff --git a/v4.0/src/DOS/SRVCALL.ASM b/v4.0/src/DOS/SRVCALL.ASM new file mode 100644 index 0000000..26064c8 --- /dev/null +++ b/v4.0/src/DOS/SRVCALL.ASM @@ -0,0 +1,306 @@ +; SCCSID = @(#)srvcall.asm 1.4 85/08/02 +TITLE SRVCALL - Server DOS call +NAME SRVCALL +; +; Server DOS call functions +; +; +; $ServerCall +; +; Modification history: +; +; Created: ARR 08 August 1983 +; + +.xlist +; +; get the appropriate segment definitions +; +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +.cref +.list + +AsmVars + +include dpl.asm + +Installed = TRUE + + i_need USER_ID,WORD + i_need PROC_ID,WORD + i_need SaveBX,WORD + i_need SaveDS,WORD + i_need SWAP_START,BYTE + i_need SWAP_ALWAYS,BYTE + i_need SWAP_END,BYTE + I_Need ThisSFT,DWORD + I_need fSharing,BYTE + i_need OpenBuf,128 + I_Need ExtErr,WORD + I_Need ExtErr_Action,BYTE + I_Need ExtErrPt,DWORD + I_Need EXTERR_LOCUS,BYTE ; Extended Error Locus + i_need JShare,DWORD + i_need SWAP_AREA_TABLE,BYTE + i_need SWAP_ALWAYS_AREA,DWORD + i_need SWAP_ALWAYS_AREA_LEN,WORD + i_need SWAP_AREA_LEN,WORD + +BREAK + +TABLE SEGMENT +Public SRVC001S,SRVC001E +SRVC001S label byte + +ServerTab DW DOSGroup:Server_Disp +SERVERLEAVE DW DOSGROUP:ServerReturn +SERVER_DISP DB (SERVER_DISP_END-SERVER_DISP-1)/2 + DW OFFSET DOSGROUP:SRV_CALL ; 0 + DW OFFSET DOSGROUP:COMMIT_ALL ; 1 + DW OFFSET DOSGROUP:CLOSE_NAME ; 2 + DW OFFSET DOSGROUP:CLOSE_UID ; 3 + DW OFFSET DOSGROUP:CLOSE_UID_PID ; 4 + DW OFFSET DOSGROUP:GET_LIST ; 5 + DW OFFSET DOSGROUP:GET_DOS_DATA ; 6 + DW OFFSET DOSGROUP:SPOOL_OPER ; 7 + DW OFFSET DOSGROUP:SPOOL_OPER ; 8 + DW OFFSET DOSGROUP:SPOOL_OPER ; 9 + DW OFFSET DOSGroup:$setExtendedError ; 10 +SERVER_DISP_END LABEL BYTE + +SRVC001E label byte + +TABLE ENDS + +; Inputs: +; DS:DX -> DPL (except calls 7,8,9) +; Function: +; AL=0 Server DOS call +; AL=1 Commit All files +; AL=2 Close file by name (SHARING LOADED ONLY) DS:DX in DPL -> name +; AL=3 Close all files for DPL_UID +; AL=4 Close all files for DPL_UID/PID_PID +; AL=5 Get open file list entry +; IN: BX File Index +; CX User Index +; OUT:ES:DI -> Name +; BX = UID +; CX = # locked blocks held by this UID +; AL=6 Get DOS data area +; OUT: DS:SI -> Start +; CX size in bytes of swap if indos +; DX size in bytes of swap always +; AL=7 Get truncate flag +; AL=8 Set truncate flag +; AL=9 Close all spool files +; AL=10 SetExtendedError +; AL=11 DOS4.00 Get DOS data area +; DS:SI -> swap table + + procedure $ServerCall,NEAR +ASSUME DS:NOTHING,ES:NOTHING + CMP AL,7 + JB SET_STUFF + CMP AL,9 + JBE NO_SET_ID ; No DPL on calls 7,8,9 + CMP AL,11 ;IFS. ;AN000; + JNZ SET_STUFF ;IFS. ;AN000; + MOV DI,OFFSET DOSGROUP:SWAP_AREA_TABLE ;IFS. ;AN000; + PUSH SS ;IFS. ;AN000; + POP ES ;IFS. ;AN000; + invoke GET_USER_STACK ;IFS. ;AN000; + MOV [SI.user_DS],ES ;IFS. ds:si -> swap tab ;AN000; + MOV [SI.user_SI],DI ;IFS. ;AN000; + transfer SYS_RET_OK ;IFS. ;AN000; +SET_STUFF: + MOV SI,DX ; Point to DPL with DS:SI + MOV BX,[SI.DPL_UID] + MOV [USER_ID],BX ; Set UID + MOV BX,[SI.DPL_PID] + MOV [PROC_ID],BX ; Set process ID +NO_SET_ID: + PUSH SERVERLEAVE ; push return address + PUSH ServerTab ; push table address + PUSH AX + Invoke TableDispatch + MOV EXTERR_LOCUS,errLoc_Unk ; Extended Error Locus + error error_invalid_function +ServerReturn: + return + +; Commit - iterate through the open file list and make sure that the +; directory entries are correctly updated. + +COMMIT_ALL: +ASSUME DS:NOTHING,ES:NOTHING + XOR BX,BX ; for (i=0; ThisSFT=getSFT(i); i++) + Context DS + EnterCrit critSFT ; Gonna scan SFT cache, lock it down +CommitLoop: + SaveReg + Invoke SFFromSFN + JC CommitDone + CMP ES:[DI].sf_Ref_Count,0 ; if (ThisSFT->refcount != 0) + JZ CommitNext + CMP ES:[DI].sf_Ref_Count,sf_busy ; BUSY SFTs have god knows what + JZ CommitNext ; in them. +; TEST ES:[DI].sf_flags,sf_isnet + invoke Test_IFS_Remote ;IFS. ;AN000; + JNZ CommitNext ; Skip Network SFTs so the SERVER + ; doesn't deadlock + MOV WORD PTR ThisSFT,DI + MOV WORD PTR ThisSFT+2,ES + Invoke DOS_Commit ; DOSCommit (); +CommitNext: + RestoreReg + INC BX + JMP CommitLoop +CommitDone: + LeaveCrit critSFT + RestoreReg + transfer Sys_Ret_OK + +CLOSE_NAME: +ASSUME DS:NOTHING,ES:NOTHING + +if installed + Call JShare + 5 * 4 +else + Call MFTcloN +endif +CheckReturns: + JC func_err + transfer SYS_RET_OK +func_err: + transfer SYS_RET_ERR + +CLOSE_UID: +ASSUME DS:NOTHING,ES:NOTHING + +if installed + Call JShare + 3 * 4 +else + Call MFTclU +endif + JMP CheckReturns + +CLOSE_UID_PID: +ASSUME DS:NOTHING,ES:NOTHING + +if installed + Call JShare + 4 * 4 +else + Call MFTCloseP +endif + JMP CheckReturns + +GET_LIST: +ASSUME DS:NOTHING,ES:NOTHING +if installed + Call JShare + 9 * 4 +else + Call MFT_get +endif + JC func_err + invoke get_user_stack + MOV [SI.user_BX],BX + MOV [SI.user_DI],DI + MOV [SI.user_ES],ES +SetCXOK: + MOV [SI.user_CX],CX + transfer SYS_RET_OK + +SRV_CALL: +ASSUME DS:NOTHING,ES:NOTHING + POP AX ; get rid of call to $srvcall + SaveReg + invoke GET_USER_STACK + RestoreReg +; +; DS:SI point to stack +; ES:DI point to DPL +; + invoke XCHGP +; +; DS:SI point to DPL +; ES:DI point to stack +; +; We now copy the registers from DPL to save stack +; + SaveReg + MOV CX,6 + REP MOVSW ; Put in AX,BX,CX,DX,SI,DI + INC DI + INC DI ; Skip user_BP + MOVSW ; DS + MOVSW ; ES + RestoreReg ; DS:SI -> DPL + MOV AX,[SI.DPL_AX] + MOV BX,[SI.DPL_BX] + MOV CX,[SI.DPL_CX] + MOV DX,[SI.DPL_DX] + MOV DI,[SI.DPL_DI] + MOV ES,[SI.DPL_ES] + PUSH [SI.DPL_SI] + MOV DS,[SI.DPL_DS] + POP SI + MOV [SaveDS],DS + MOV [SaveBX],BX + MOV fSharing,-1 ; set no redirect flag + transfer REDISP + +GET_DOS_DATA: +ASSUME DS:NOTHING,ES:NOTHING + LES DI,[SWAP_ALWAYS_AREA] ;IFS. get beginning addr of swap ;AC000; + MOV DX,[SWAP_ALWAYS_AREA_LEN] ;IFS. get swap always area len ;AC000; + AND DX,7FFFH ;IFS. clear high bit ;AC000; + MOV CX,[SWAP_AREA_LEN] ;IFS. get swap len ;AC000; + invoke GET_USER_STACK + MOV [SI.user_DS],ES ; set user regs + MOV [SI.user_SI],DI ; + MOV [SI.user_DX],DX ; + JMP SetCXOK ; ;AN000; + +SPOOL_OPER: +ASSUME DS:NOTHING,ES:NOTHING + CallInstall NETSpoolOper,multNet,37,AX,BX + JC func_err2 + transfer SYS_RET_OK +func_err2: + transfer SYS_RET_ERR + +Break <$SetExtendedError - set extended error for later retrieval> + +; +; $SetExtendedError takes extended error information and loads it up for the +; next extended error call. This is used by interrupt-level proccessors to +; mask their actions. +; +; Inputs: DS:SI points to DPL which contains all registers +; Outputs: none +; + +$SetExtendedError: + ASSUME DS:NOTHING,ES:NOTHING + MOV AX,[SI].dpl_AX + MOV [EXTERR],AX + MOV AX,[SI].dpL_di + MOV WORD PTR ExtErrPt,AX + MOV AX,[SI].dpL_ES + MOV WORD PTR ExtErrPt+2,AX + MOV AX,[SI].dpL_BX + MOV WORD PTR [EXTERR_ACTION],AX + MOV AX,[SI].dpL_CX + MOV [EXTERR_LOCUS],AH + return +EndProc $ServerCall + +CODE ENDS + END diff --git a/v4.0/src/DOS/STDASW.ASM b/v4.0/src/DOS/STDASW.ASM new file mode 100644 index 0000000..d9fa382 --- /dev/null +++ b/v4.0/src/DOS/STDASW.ASM @@ -0,0 +1,29 @@ +; SCCSID = @(#)stdasw.asm 1.1 85/04/10 +TRUE EQU 0FFFFH +FALSE EQU NOT TRUE + +; Use the switches below to produce the standard Microsoft version or the IBM +; version of the operating system +MSVER EQU TRUE +IBM EQU FALSE +WANG EQU FALSE +ALTVECT EQU TRUE + +; Set this switch to cause DOS to move itself to the end of memory +HIGHMEM EQU FALSE + + IF IBM +ESCCH EQU 0 ; character to begin escape seq. +TOGLPRN EQU TRUE ;One key toggles printer echo +ZEROEXT EQU TRUE + ELSE + IF WANG ;Are we assembling for WANG? +ESCCH EQU 1FH ;Yes. Use 1FH for escape character + ELSE +ESCCH EQU 1BH + ENDIF +CANCEL EQU "X"-"@" ;Cancel with Ctrl-X +TOGLPRN EQU FALSE ;Separate keys for printer echo on + ;and off +ZEROEXT EQU TRUE + ENDIF diff --git a/v4.0/src/DOS/STDCODE.ASM b/v4.0/src/DOS/STDCODE.ASM new file mode 100644 index 0000000..0332898 --- /dev/null +++ b/v4.0/src/DOS/STDCODE.ASM @@ -0,0 +1,17 @@ +; SCCSID = @(#)stdcode.asm 1.1 85/04/10 +TITLE MS-DOS MISC DOS ROUTINES - Int 25 and 26 handlers and other +NAME STDCODE + +; +; System call dispatch code +; + +.xlist +.xcref +include stdsw.asm +.cref +.list + +include ms_code.asm + END + \ No newline at end of file diff --git a/v4.0/src/DOS/STDCPMIO.ASM b/v4.0/src/DOS/STDCPMIO.ASM new file mode 100644 index 0000000..44bbb57 --- /dev/null +++ b/v4.0/src/DOS/STDCPMIO.ASM @@ -0,0 +1,16 @@ +; SCCSID = @(#)stdcpmio.asm 1.1 85/04/10 +; +; Standard device IO for MSDOS (first 12 function calls) +; + +.xlist +.xcref +include stdsw.asm +include dosseg.asm +.cref +.list + +TITLE STDCPMIO - device IO for MSDOS +NAME STDCPMIO + +include cpmio.asm diff --git a/v4.0/src/DOS/STDCTRLC.ASM b/v4.0/src/DOS/STDCTRLC.ASM new file mode 100644 index 0000000..90af372 --- /dev/null +++ b/v4.0/src/DOS/STDCTRLC.ASM @@ -0,0 +1,15 @@ +; SCCSID = @(#)stdctrlc.asm 1.1 85/04/10 +; +; ^C and error handler for MSDOS +; + +.xlist +.xcref +include stdsw.asm +.cref +.list + +TITLE Control C detection, Hard error and EXIT routines +NAME STDCTRLC + +include ctrlc.asm diff --git a/v4.0/src/DOS/STDDATA.ASM b/v4.0/src/DOS/STDDATA.ASM new file mode 100644 index 0000000..ddbb1bc --- /dev/null +++ b/v4.0/src/DOS/STDDATA.ASM @@ -0,0 +1,33 @@ +; SCCSID = @(#)stddata.asm 1.1 85/04/10 +; +; DATA Segment for MS-DOS +; + +.xlist +.xcref +include stdsw.asm +include dosseg.asm +debug = FALSE ; No dossym (too big) +INCLUDE DOSMAC.INC +INCLUDE SF.INC +INCLUDE DIRENT.INC +INCLUDE CURDIR.INC +INCLUDE DPB.INC +INCLUDE BUFFER.INC +INCLUDE ARENA.INC +INCLUDE VECTOR.INC +INCLUDE DEVSYM.INC +INCLUDE PDB.INC +INCLUDE FIND.INC +INCLUDE MI.INC +.cref +.list + +TITLE STDDATA - DATA segment for MS-DOS +NAME STDDATA + +installed = TRUE + +include msdata.asm +include msinit.asm + END diff --git a/v4.0/src/DOS/STDDISP.ASM b/v4.0/src/DOS/STDDISP.ASM new file mode 100644 index 0000000..9010b98 --- /dev/null +++ b/v4.0/src/DOS/STDDISP.ASM @@ -0,0 +1,16 @@ +; SCCSID = @(#)stddisp.asm 1.1 85/04/10 +TITLE MS-DOS DOS DISPATCHER - System call dispatch code +NAME DISP + +; +; System call dispatch code +; + +.xlist +.xcref +include stdsw.asm +.cref +.list + +include disp.asm + END diff --git a/v4.0/src/DOS/STDDOSME.ASM b/v4.0/src/DOS/STDDOSME.ASM new file mode 100644 index 0000000..c1d5a53 --- /dev/null +++ b/v4.0/src/DOS/STDDOSME.ASM @@ -0,0 +1,20 @@ +; SCCSID = @(#)stddosmes.as 1.2 85/10/07 +; SCCSID = @(#)stddosmes.as 1.2 85/10/07 +; +; Standard device IO for MSDOS (first 12 function calls) +; + +.xlist +.xcref +include stdsw.asm +include dosseg.asm +.cref +.list + +debug=0 + +TITLE STDDOSMES - DOS OEM dependancies +NAME STDDOSMES + +include dosmes.asm + \ No newline at end of file diff --git a/v4.0/src/DOS/STDIOCTL.ASM b/v4.0/src/DOS/STDIOCTL.ASM new file mode 100644 index 0000000..9444530 --- /dev/null +++ b/v4.0/src/DOS/STDIOCTL.ASM @@ -0,0 +1,5 @@ +; SCCSID = @(#)STDIOCTL.INC 1.1 85/04/10 +IBM EQU 0 ;FALSE + +INCLUDE IOCTL.INC + SCCSID = @(#)STDIOCTL.INC 1.1 85/04/10 diff --git a/v4.0/src/DOS/STDPROC.ASM b/v4.0/src/DOS/STDPROC.ASM new file mode 100644 index 0000000..c83fe2b --- /dev/null +++ b/v4.0/src/DOS/STDPROC.ASM @@ -0,0 +1,15 @@ +; SCCSID = @(#)stdproc.asm 1.1 85/04/10 +; +; Pseudo EXEC system call for MSDOS +; + +.xlist +.xcref +include stdsw.asm +.cref +.list + +TITLE STDPROC - process maintenance for MSDOS +NAME STDPROC + +include proc.asm diff --git a/v4.0/src/DOS/STDSW.ASM b/v4.0/src/DOS/STDSW.ASM new file mode 100644 index 0000000..c9fc581 --- /dev/null +++ b/v4.0/src/DOS/STDSW.ASM @@ -0,0 +1,32 @@ +; SCCSID = @(#)stdsw.asm 1.1 85/04/10 +TRUE EQU 0FFFFH +FALSE EQU 0 + +; Use the switches below to produce the standard Microsoft version or the IBM +; version of the operating system +MSVER EQU TRUE +IBM EQU FALSE +WANG EQU FALSE +ALTVECT EQU FALSE +Rainbow EQU FALSE + + +; Set this switch to cause DOS to move itself to the end of memory +HIGHMEM EQU FALSE + + IF IBM +ESCCH EQU 0 ; character to begin escape seq. +CANCEL EQU 27 ;Cancel with ESCAPE +TOGLPRN EQU TRUE ;One key toggles printer echo +ZEROEXT EQU TRUE + ELSE + IF WANG ;Are we assembling for WANG? +ESCCH EQU 1FH ;Yes. Use 1FH for escape character + ELSE +ESCCH EQU 1BH + ENDIF +CANCEL EQU "X"-"@" ;Cancel with Ctrl-X +TOGLPRN EQU FALSE ;Separate keys for printer echo on + ;and off +ZEROEXT EQU TRUE + ENDIF diff --git a/v4.0/src/DOS/STDTABLE.ASM b/v4.0/src/DOS/STDTABLE.ASM new file mode 100644 index 0000000..a06b3e6 --- /dev/null +++ b/v4.0/src/DOS/STDTABLE.ASM @@ -0,0 +1,16 @@ +; SCCSID = @(#)stdtable.asm 1.1 85/04/10 +; +; Table Segment for MS-DOS DOS +; + +.xlist +.xcref +include stdsw.asm +.cref +.list + +TITLE STDTABLE - Table segment for MS-DOS +NAME STDTABLE + +include mstable.asm + END diff --git a/v4.0/src/DOS/STRIN.ASM b/v4.0/src/DOS/STRIN.ASM new file mode 100644 index 0000000..ac4b963 --- /dev/null +++ b/v4.0/src/DOS/STRIN.ASM @@ -0,0 +1,403 @@ +; SCCSID = @(#)strin.asm 1.2 85/04/18 +Break + +; Inputs: +; DS:DX Point to an input buffer +; Function: +; Fill buffer from console input until CR +; Returns: +; None + + procedure $STD_CON_STRING_INPUT,NEAR ;System call 10 +ASSUME DS:NOTHING,ES:NOTHING + + MOV AX,SS + MOV ES,AX + MOV SI,DX + XOR CH,CH + LODSW +; +; AL is the buffer length +; AH is the template length +; + OR AL,AL + retz ;Buffer is 0 length!!? + MOV BL,AH ;Init template counter + MOV BH,CH ;Init template counter + ; + ; BL is the number of bytes in the template + ; + CMP AL,BL + JBE NOEDIT ;If length of buffer inconsistent with contents + CMP BYTE PTR [BX+SI],c_CR + JZ EDITON ;If CR correctly placed EDIT is OK +; +; The number of chars in the template is >= the number of chars in buffer or +; there is no CR at the end of the template. This is an inconsistant state +; of affairs. Pretend that the template was empty: +; +NOEDIT: + MOV BL,CH ;Reset buffer +EDITON: + MOV DL,AL + DEC DX ;DL is # of bytes we can put in the buffer +; +; Top level. We begin to read a line in. +; +NEWLIN: + MOV AL,[CARPOS] + MOV [STARTPOS],AL ;Remember position in raw buffer + PUSH SI + MOV DI,OFFSET DOSGROUP:INBUF ;Build the new line here + MOV [INSMODE],CH ;Insert mode off + MOV BH,CH ;No chars from template yet + MOV DH,CH ;No chars to new line yet + invoke $STD_CON_INPUT_NO_ECHO ;Get first char + CMP AL,c_LF ;Linefeed + JNZ GOTCH ;Filter out LF so < works +; +; This is the main loop of reading in a character and processing it. +; +; BH is the index of the next byte in the template +; BL is the length of the template +; DH is the number of bytes in the buffer +; DL is the length of the buffer +; +entry GETCH + invoke $STD_CON_INPUT_NO_ECHO +GOTCH: +; +; Brain-damaged TP ignored ^F in case his BIOS did not flush the +; input queue. +; + CMP AL,"F"-"@" + JZ GETCH +; +; If the leading char is the function-key lead byte +; + CMP AL,[ESCCHAR] + JZ ESCape ;change reserved keyword DBM 5-7-87 +; +; Rubout and ^H are both destructive backspaces. +; + CMP AL,c_DEL + JZ BACKSPJ + CMP AL,c_BS + JZ BACKSPJ +; +; ^W deletes backward once and then backs up until a letter is before the +; cursor +; + CMP AL,"W" - "@" +; The removal of the comment characters before the jump statement will +; cause ^W to backup a word. +;*** JZ WordDel + NOP + NOP + CMP AL,"U" - "@" +; The removal of the comment characters before the jump statement will +; cause ^U to clear a line. +;*** JZ LineDel + NOP + NOP + +; +; CR terminates the line. +; + CMP AL,c_CR + JZ ENDLIN +; +; LF goes to a new line and keeps on reading. +; + CMP AL,c_LF + JZ PHYCRLF +; +; ^X (or ESC) deletes the line and starts over +; + CMP AL,[CANCHAR] + JZ KILNEW +; +; Otherwise, we save the input character. +; +SAVCH: + CMP DH,DL + JAE BUFFUL ; buffer is full. + STOSB + INC DH ; increment count in buffer. + invoke BUFOUT ;Print control chars nicely + CMP BYTE PTR [INSMODE],0 + JNZ GETCH ; insertmode => don't advance template + CMP BH,BL + JAE GETCH ; no more characters in template + INC SI ; Skip to next char in template + INC BH ; remember position in template + JMP SHORT GETCH + +BACKSPJ: JMP SHORT BACKSP + +BUFFUL: + MOV AL,7 ; Bell to signal full buffer + invoke OUTT + JMP SHORT GETCH + +ESCape: ;change reserved keyword DBM 5-7-87 + transfer OEMFunctionKey ; let the OEM's handle the key dispatch + +ENDLIN: + STOSB ; Put the CR in the buffer + invoke OUTT ; Echo it + POP DI ; Get start of user buffer + MOV [DI-1],DH ; Tell user how many bytes + INC DH ; DH is length including CR +COPYNEW: + SaveReg + RestoreReg ; XCHG ES,DS + MOV SI,OFFSET DOSGROUP:INBUF + MOV CL,DH ; set up count + REP MOVSB ; Copy final line to user buffer + return +; +; Output a CRLF to the user screen and do NOT store it into the buffer +; +PHYCRLF: + invoke CRLF + JMP GETCH + +; +; Delete the previous line +; +LineDel: + OR DH,DH + JZ GetCh + Call BackSpace + JMP LineDel + +; +; delete the previous word. +; +WordDel: +WordLoop: + Call BackSpace ; backspace the one spot + OR DH,DH + JZ GetChJ + MOV AL,ES:[DI-1] + cmp al,'0' + jb GetChj + cmp al,'9' + jbe WordLoop + OR AL,20h + CMP AL,'a' + JB GetChJ + CMP AL,'z' + JBE WordLoop +GetChJ: + JMP GetCh +; +; The user wants to throw away what he's typed in and wants to start over. We +; print the backslash and then go to the next line and tab to the correct spot +; to begin the buffered input. +; + entry KILNEW + MOV AL,"\" + invoke OUTT ;Print the CANCEL indicator + POP SI ;Remember start of edit buffer +PUTNEW: + invoke CRLF ;Go to next line on screen + MOV AL,[STARTPOS] + invoke TAB ;Tab over + JMP NEWLIN ;Start over again + + +; +; Destructively back up one character position +; +entry BackSp + Call BackSpace + JMP GetCh + +BackSpace: + OR DH,DH + JZ OLDBAK ;No chars in line, do nothing to line + CALL BACKUP ;Do the backup + MOV AL,ES:[DI] ;Get the deleted char + CMP AL," " + JAE OLDBAK ;Was a normal char + CMP AL,c_HT + JZ BAKTAB ;Was a tab, fix up users display +;; 9/27/86 fix for ctrl-U backspace + CMP AL,"U"-"@" ; ctrl-U is a section symbol not ^U + JZ OLDBAK + CMP AL,"T"-"@" ; ctrl-T is a paragraphs symbol not ^T + JZ OLDBAK +;; 9/27/86 fix for ctrl-U backspace + CALL BACKMES ;Was a control char, zap the '^' +OLDBAK: + CMP BYTE PTR [INSMODE],0 + retnz ;In insert mode, done + OR BH,BH + retz ;Not advanced in template, stay where we are + DEC BH ;Go back in template + DEC SI + return + +BAKTAB: + PUSH DI + DEC DI ;Back up one char + STD ;Go backward + MOV CL,DH ;Number of chars currently in line + MOV AL," " + PUSH BX + MOV BL,7 ;Max + JCXZ FIGTAB ;At start, do nothing +FNDPOS: + SCASB ;Look back + JNA CHKCNT + CMP BYTE PTR ES:[DI+1],9 + JZ HAVTAB ;Found a tab + DEC BL ;Back one char if non tab control char +CHKCNT: + LOOP FNDPOS +FIGTAB: + SUB BL,[STARTPOS] +HAVTAB: + SUB BL,DH + ADD CL,BL + AND CL,7 ;CX has correct number to erase + CLD ;Back to normal + POP BX + POP DI + JZ OLDBAK ;Nothing to erase +TABBAK: + invoke BACKMES + LOOP TABBAK ;Erase correct number of chars + JMP SHORT OLDBAK + +BACKUP: + DEC DH ;Back up in line + DEC DI +BACKMES: + MOV AL,c_BS ;Backspace + invoke OUTT + MOV AL," " ;Erase + invoke OUTT + MOV AL,c_BS ;Backspace + JMP OUTT ;Done + +;User really wants an ESC character in his line + entry TwoEsc + MOV AL,[ESCCHAR] + JMP SAVCH + +;Copy the rest of the template + entry COPYLIN + MOV CL,BL ;Total size of template + SUB CL,BH ;Minus position in template, is number to move + JMP SHORT COPYEACH + + entry CopyStr + invoke FINDOLD ;Find the char + JMP SHORT COPYEACH ;Copy up to it + +;Copy one char from template to line + entry COPYONE + MOV CL,1 +;Copy CX chars from template to line +COPYEACH: + MOV BYTE PTR [INSMODE],0 ;All copies turn off insert mode + CMP DH,DL + JZ GETCH2 ;At end of line, can't do anything + CMP BH,BL + JZ GETCH2 ;At end of template, can't do anything + LODSB + STOSB + invoke BUFOUT + INC BH ;Ahead in template + INC DH ;Ahead in line + LOOP COPYEACH +GETCH2: + JMP GETCH + +;Skip one char in template + entry SKIPONE + CMP BH,BL + JZ GETCH2 ;At end of template + INC BH ;Ahead in template + INC SI + JMP GETCH + + entry SKIPSTR + invoke FINDOLD ;Find out how far to go + ADD SI,CX ;Go there + ADD BH,CL + JMP GETCH + +;Get the next user char, and look ahead in template for a match +;CX indicates how many chars to skip to get there on output +;NOTE: WARNING: If the operation cannot be done, the return +; address is popped off and a jump to GETCH is taken. +; Make sure nothing extra on stack when this routine +; is called!!! (no PUSHes before calling it). +FINDOLD: + invoke $STD_CON_INPUT_NO_ECHO + CMP AL,[ESCCHAR] ; did he type a function key? + JNZ FindSetup ; no, set up for scan + invoke $STD_CON_INPUT_NO_ECHO ; eat next char + JMP NotFnd ; go try again +FindSetup: + MOV CL,BL + SUB CL,BH ;CX is number of chars to end of template + JZ NOTFND ;At end of template + DEC CX ;Cannot point past end, limit search + JZ NOTFND ;If only one char in template, forget it + PUSH ES + PUSH DS + POP ES + PUSH DI + MOV DI,SI ;Template to ES:DI + INC DI + REPNE SCASB ;Look + POP DI + POP ES + JNZ NOTFND ;Didn't find the char + NOT CL ;Turn how far to go into how far we went + ADD CL,BL ;Add size of template + SUB CL,BH ;Subtract current pos, result distance to skip + return + +NOTFND: + POP BP ;Chuck return address + JMP GETCH + +entry REEDIT + MOV AL,"@" ;Output re-edit character + invoke OUTT + POP DI + PUSH DI + PUSH ES + PUSH DS + invoke COPYNEW ;Copy current line into template + POP DS + POP ES + POP SI + MOV BL,DH ;Size of line is new size template + JMP PUTNEW ;Start over again + + entry EXITINS + entry ENTERINS + NOT BYTE PTR [INSMODE] + JMP GETCH + +;Put a real live ^Z in the buffer (embedded) + entry CTRLZ + MOV AL,"Z"-"@" + JMP SAVCH + +;Output a CRLF + entry CRLF + MOV AL,c_CR + invoke OUTT + MOV AL,c_LF + JMP OUTT + +EndProc $STD_CON_STRING_INPUT + \ No newline at end of file diff --git a/v4.0/src/DOS/TIME.ASM b/v4.0/src/DOS/TIME.ASM new file mode 100644 index 0000000..0d3895c --- /dev/null +++ b/v4.0/src/DOS/TIME.ASM @@ -0,0 +1,380 @@ +; SCCSID = @(#)time.asm 1.1 85/04/10 +TITLE TIME - time and date functions +NAME TIME +; +; System Calls and low level routines for DATE and TIME +; +; $GET_DATE +; $SET_DATE +; $GET_TIME +; $SET_TIME +; DATE16 +; READTIME +; DSLIDE +; SETYEAR +; DODATE +; DSUM +; +; Modification history: +; +; Created: ARR 30 March 1983 +; + +.xlist +; +; get the appropriate segment definitions +; +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +.cref +.list + + + i_need DAY,BYTE + i_need MONTH,BYTE + i_need YEAR,WORD + i_need WEEKDAY,BYTE + i_need TIMEBUF,6 + i_need BCLOCK,DWORD + i_need DAYCNT,WORD + i_need YRTAB,8 + i_need MONTAB,12 + i_need DATE_FLAG,WORD + + FOURYEARS = 3*365 + 366 + +SUBTTL DATE AND TIME - SYSTEM CALLS 42,43,44,45 +PAGE + procedure $GET_DATE,NEAR +ASSUME DS:NOTHING,ES:NOTHING + +; Inputs: +; None +; Function: +; Return current date +; Returns: +; Date in CX:DX + + Context DS + CALL READTIME ;Check for rollover to next day + MOV AX,[YEAR] +; +; WARNING!!!! DAY and MONTH must be adjacently allocated! +; + MOV BX,WORD PTR [DAY] ; fetch both day and month + invoke get_user_stack ;Get pointer to user registers +ASSUME DS:NOTHING + MOV [SI.user_DX],BX ;DH=month, DL=day + ADD AX,1980 ;Put bias back + MOV [SI.user_CX],AX ;CX=year + MOV AL,BYTE PTR [WEEKDAY] + return +EndProc $GET_DATE + + procedure $SET_DATE,NEAR ;System call 43 +ASSUME DS:NOTHING,ES:NOTHING + +; Inputs: +; CX:DX valid date +; Function: +; Set current date +; Returns: +; AL = -1 date bad, = 0 OK + + MOV AL,-1 ;Be ready to flag error + SUB CX,1980 ;Fix bias in year + retc ;Error if not big enough + CMP CX,119 ;Year must be less than 2100 + JA RET24 + OR DH,DH + retz + OR DL,DL + retz ;Error if either month or day is 0 + CMP DH,12 ;Check against max. month + JA RET24 + Context DS + invoke DODATE +RET24: return +EndProc $SET_DATE + + procedure $GET_TIME,NEAR ;System call 44 +ASSUME DS:NOTHING,ES:NOTHING + +; Inputs: +; None +; Function: +; Get current time +; Returns: +; Time in CX:DX + + Context DS + CALL READTIME + invoke get_user_stack ;Get pointer to user registers + MOV [SI.user_DX],DX + MOV [SI.user_CX],CX + XOR AL,AL +RET26: return +EndProc $GET_TIME + + procedure $SET_TIME,NEAR ;System call 45 +ASSUME DS:NOTHING,ES:NOTHING + +; Inputs: +; CX:DX = Time +; Function: +; Set time +; Returns: +; AL = -1 time bad, = 0 OK + + MOV AL,-1 ;Flag in case of error + CMP CH,24 ;Check hours + JAE RET26 + CMP CL,60 ;Check minutes + JAE RET26 + CMP DH,60 ;Check seconds + JAE RET26 + CMP DL,100 ;Check 1/100's + JAE RET26 + PUSH CX + PUSH DX + Context DS + MOV BX,OFFSET DOSGROUP:TIMEBUF + MOV CX,6 + XOR DX,DX + MOV AX,DX + PUSH BX + invoke SETREAD + DOSAssume CS,,"TIME/SetRead" + PUSH DS + LDS SI,[BCLOCK] +ASSUME DS:NOTHING + invoke DEVIOCALL2 ;Get correct day count + POP DS + DOSAssume CS,,"TIME/DevIOCall2" + POP BX + invoke SETWRITE + POP WORD PTR [TIMEBUF+4] + POP WORD PTR [TIMEBUF+2] + LDS SI,[BCLOCK] +ASSUME DS:NOTHING + invoke DEVIOCALL2 ;Set the time + XOR AL,AL + return +EndProc $SET_TIME + +SUBTTL DATE16, READTIME, DODATE -- GUTS OF TIME AND DATE +PAGE + +; +; Date16 returns the current date in AX, current time in DX +; AX - YYYYYYYMMMMDDDDD years months days +; DX - HHHHHMMMMMMSSSSS hours minutes seconds/2 +; +; DS = DOSGROUP on output + +procedure DATE16,NEAR + Context DS + ASSUME ES:NOTHING + PUSH CX + PUSH ES + CALL READTIME + POP ES + SHL CL,1 ;Minutes to left part of byte + SHL CL,1 + SHL CX,1 ;Push hours and minutes to left end + SHL CX,1 + SHL CX,1 + SHR DH,1 ;Count every two seconds + OR CL,DH ;Combine seconds with hours and minutes + MOV DX,CX +; +; WARNING! MONTH and YEAR must be adjacently allocated +; + MOV AX,WORD PTR [MONTH] ;Fetch month and year + MOV CL,4 + SHL AL,CL ;Push month to left to make room for day + SHL AX,1 + POP CX + OR AL,[DAY] + return +EndProc DATE16 + +;Gets time in CX:DX. Figures new date if it has changed. +;Uses AX, CX, DX. + + procedure READTIME,NEAR + DOSAssume CS,,"ReadTime" + ASSUME ES:NOTHING + + MOV [DATE_FLAG],0 ; reset date flag for CPMIO + PUSH SI + PUSH BX + MOV BX,OFFSET DOSGROUP:TIMEBUF + MOV CX,6 + XOR DX,DX + MOV AX,DX + invoke SETREAD + PUSH DS + LDS SI,[BCLOCK] +ASSUME DS:NOTHING + invoke DEVIOCALL2 ;Get correct date and time + POP DS + DOSAssume CS,,"ReadTime/DevIOCall2" + POP BX + POP SI + MOV AX,WORD PTR [TIMEBUF] + MOV CX,WORD PTR [TIMEBUF+2] + MOV DX,WORD PTR [TIMEBUF+4] + CMP AX,[DAYCNT] ;See if day count is the same + retz + CMP AX,FOURYEARS*30 ;Number of days in 120 years + JAE RET22 ;Ignore if too large + MOV [DAYCNT],AX + PUSH SI + PUSH CX + PUSH DX ;Save time + XOR DX,DX + MOV CX,FOURYEARS ;Number of days in 4 years + DIV CX ;Compute number of 4-year units + SHL AX,1 + SHL AX,1 + SHL AX,1 ;Multiply by 8 (no. of half-years) + MOV CX,AX ;<240 implies AH=0 + MOV SI,OFFSET DOSGROUP:YRTAB;Table of days in each year + CALL DSLIDE ;Find out which of four years we're in + SHR CX,1 ;Convert half-years to whole years + JNC SK ;Extra half-year? + ADD DX,200 +SK: + CALL SETYEAR + MOV CL,1 ;At least at first month in year + MOV SI,OFFSET DOSGROUP:MONTAB ;Table of days in each month + CALL DSLIDE ;Find out which month we're in + MOV [MONTH],CL + INC DX ;Remainder is day of month (start with one) + MOV [DAY],DL + CALL WKDAY ;Set day of week + POP DX + POP CX + POP SI +RET22: return +EndProc READTIME + + procedure DSLIDE,NEAR + MOV AH,0 +DSLIDE1: + LODSB ;Get count of days + CMP DX,AX ;See if it will fit + retc ;If not, done + SUB DX,AX + INC CX ;Count one more month/year + JMP SHORT DSLIDE1 +EndProc DSLIDE + + procedure SETYEAR,NEAR +;Set year with value in CX. Adjust length of February for this year. + MOV BYTE PTR [YEAR],CL + +CHKYR: + TEST CL,3 ;Check for leap year + MOV AL,28 + JNZ SAVFEB ;28 days if no leap year + INC AL ;Add leap day +SAVFEB: + MOV [MONTAB+1],AL ;Store for February +RET23: return +EndProc SETYEAR + + procedure DODATE,NEAR + DOSAssume CS,,"DoDate" + ASSUME ES:NOTHING + CALL CHKYR ;Set Feb. up for new year + MOV AL,DH + MOV BX,OFFSET DOSGROUP:MONTAB-1 + XLAT ;Look up days in month + CMP AL,DL + MOV AL,-1 ;Restore error flag, just in case + retc ;Error if too many days + CALL SETYEAR +; +; WARNING! DAY and MONTH must be adjacently allocated +; + MOV WORD PTR [DAY],DX ;Set both day and month + SHR CX,1 + SHR CX,1 + MOV AX,FOURYEARS + MOV BX,DX + MUL CX + MOV CL,BYTE PTR [YEAR] + AND CL,3 + MOV SI,OFFSET DOSGROUP:YRTAB + MOV DX,AX + SHL CX,1 ;Two entries per year, so double count + CALL DSUM ;Add up the days in each year + MOV CL,BH ;Month of year + MOV SI,OFFSET DOSGROUP:MONTAB + DEC CX ;Account for months starting with one + CALL DSUM ;Add up days in each month + MOV CL,BL ;Day of month + DEC CX ;Account for days starting with one + ADD DX,CX ;Add in to day total + XCHG AX,DX ;Get day count in AX + MOV [DAYCNT],AX + PUSH SI + PUSH BX + PUSH AX + MOV BX,OFFSET DOSGROUP:TIMEBUF + MOV CX,6 + XOR DX,DX + MOV AX,DX + PUSH BX + invoke SETREAD + DOSAssume CS,,"DoDate/SetRead" + PUSH DS + LDS SI,[BCLOCK] +ASSUME DS:NOTHING + invoke DEVIOCALL2 ;Get correct date and time + POP DS + POP BX + DOSAssume CS,,"DoDate/DevIOCall2" + invoke SETWRITE + POP WORD PTR [TIMEBUF] + PUSH DS + LDS SI,[BCLOCK] +ASSUME DS:NOTHING + invoke DEVIOCALL2 ;Set the date + POP DS + DOSAssume CS,,"DoDate/DevIOCall2(second)" + POP BX + POP SI +WKDAY: + MOV AX,[DAYCNT] + XOR DX,DX + MOV CX,7 + INC AX + INC AX ;First day was Tuesday + DIV CX ;Compute day of week + MOV [WEEKDAY],DL + XOR AL,AL ;Flag OK +Ret25: return +EndProc DODATE + + procedure DSUM,NEAR + MOV AH,0 + JCXZ RET25 +DSUM1: + LODSB + ADD DX,AX + LOOP DSUM1 + return +EndProc DSUM + +CODE ENDS + END + \ No newline at end of file diff --git a/v4.0/src/DOS/UTIL.ASM b/v4.0/src/DOS/UTIL.ASM new file mode 100644 index 0000000..3c9c516 --- /dev/null +++ b/v4.0/src/DOS/UTIL.ASM @@ -0,0 +1,232 @@ +; SCCSID = @(#)util.asm 1.1 85/04/10 +TITLE UTIL - Handle utilities +NAME UTIL +; +; Handle related utilities for MSDOS 2.X. +; +; pJFNFromHandle written +; SFFromHandle written +; SFFromSFN written +; JFNFree written +; SFNFree written +; +; Modification history: +; +; Created: MZ 1 April 1983 +; + +.xlist +; +; get the appropriate segment definitions +; +include dosseg.asm + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME SS:DOSGROUP,CS:DOSGROUP + +.xcref +INCLUDE DOSSYM.INC +INCLUDE DEVSYM.INC +.cref +.list +.sall + + I_need CurrentPDB,WORD ; current process data block location + I_need SFT_Addr,DWORD ; pointer to beginning of table + I_Need PROC_ID,WORD ; current process ID + I_Need USER_ID,WORD ; current user ID +if debug + I_need BugLev,WORD + I_need BugTyp,WORD +include bugtyp.asm +endif + +BREAK + +; +; pJFNFromHandle - Given a handle, return the pointer to the JFN location +; in the user's data space +; Inputs: BX - Handle +; Outputs: Carry Set +; AX has error code +; Carry reset +; ES:DI point to the handle spot +; Registers modified: +; If no error, ES:DI, else AX,ES +; NOTE: +; This routine is called from $CREATE_PROCESS_DATA_BLOCK which is called +; at DOSINIT time with SS NOT DOSGROUP +procedure pJFNFromHandle,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + MOV ES,[CurrentPDB] ; get user process data block + CMP BX,ES:[PDB_JFN_Length] ; is handle greater than allocated + JB JFNAdd ; no, get offset + fmt TypAccess,LevSFN,<"$p: Illegal JFN %x\n">, + MOV AL,error_invalid_handle ; appropriate error +ReturnCarry: + STC ; signal error + return ; go back +JFNAdd: LES DI,ES:[PDB_JFN_Pointer] ; get pointer to beginning of table + ADD DI,BX ; add in offset +ReturnNoCarry: + CLC ; no holes + return ; bye! +EndProc pJFNFromHandle + +BREAK + +; +; SFFromHandle - Given a handle, get JFN and then index into SF table +; +; Input: BX has handle +; Output: Carry Set +; AX has error code +; Carry Reset +; ES:DI has pointer to SF entry +; Registers modified: If error, AX,ES, else ES:DI +; NOTE: +; This routine is called from $CREATE_PROCESS_DATA_BLOCK which is called +; at DOSINIT time with SS NOT DOSGROUP +procedure SFFromHandle,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + CALL pJFNFromHandle ; get jfn pointer + retc ; return if error + CMP BYTE PTR ES:[DI],-1 ; unused handle + JNZ GetSF ; nope, suck out SF + fmt TypAccess,LevSFN,<"$p: Illegal SFN $x:$x\n">, + MOV AL,error_invalid_handle ; appropriate error + jump ReturnCarry ; signal it +GetSF: + SaveReg ; save handle + MOV BL,BYTE PTR ES:[DI] ; get SFN + XOR BH,BH ; ignore upper half + CALL SFFromSFN ; get real sf spot + RestoreReg ; restore + return ; say goodbye +EndProc SFFromHandle + +BREAK + +; +; SFFromSFN - index into SF tables for SFN. +; +; Input: BX has SF index +; Output: ES:DI points to SF entry +; Registers modified: ES:DI, BX only +; NOTE: +; This routine is called from SFFromHandle which is called +; at DOSINIT time with SS NOT DOSGROUP +procedure SFFromSFN,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + LES DI,[SFT_Addr] ; get pointer to beginning of table +ScanLoop: + CMP BX,ES:[DI].SFCount ; is handle in this table? + JB GetOffset ; yes, go grab it + SUB BX,ES:[DI].SFCount + LES DI,ES:[DI].SFLink ; get next table segment + CMP DI,-1 ; end of tables? + JNZ ScanLoop ; no, try again + STC ; error... + JMP SHORT Restore ; go restore +GetOffset: + SaveReg ; save AX + MOV AX,SIZE SF_Entry ; put it in a nice place + MUL BL ; times size + ADD DI,AX ; offset by size + RestoreReg ; get world back + ADD DI,SFTable ; offset into structure + CLC ; no holes +Restore: + return ; bye! +EndProc SFFromSFN + +BREAK + +; +; JFNFree - scan through the JFN table and return a pointer to a free slot +; +; Input: None. +; Output: Carry Set +; AX has error code, BX,ES,DI garbage +; Carry Reset +; BX has new handle, ES:DI is pointer to JFN slot +; Registers modified: As above only. +procedure JFNFree,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP + XOR BX,BX ; try starting low +JFNScan: + CALL pJFNFromHandle ; get the appropriate handle + JC JFNNone ; no more handles + CMP BYTE PTR ES:[DI],-1 ; free? + JZ JFNFound ; yes, carry is clear + INC BX ; no, next handle + JMP JFNScan ; and try again +JFNNone: + MOV AL,error_too_many_open_files +JFNFound: + return ; bye +EndProc JFNFree + +BREAK + +; +; SFNFree - scan through the sf table looking for free entries +; Inputs: none +; Outputs: Carry Set - AX has error code, BX destroyed +; Carry Clear - BX has SFN +; ES:DI - pointer to SFT +; SFT_ref_count is set to 1 +; Registers modified: none + +Procedure SFNFree,NEAR + ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGROUP + XOR BX,BX ; start at beginning +SFNFreeLoop: + SaveReg ; Next call zaps BX + CALL SFFromSFN ; get the potential handle + RestoreReg + JNC SFNCheck ; no carry, check to see if its free + MOV AL,error_too_many_open_files ; appropriate error + JMP SFNDone +SFNCheck: + CMP ES:[DI.sf_Ref_Count],0 ; free? +IF NOT DEBUG + JZ SFNGot ; yep, got return him +ELSE + JNZ NoGot + JMP SFNGot +NoGot: +ENDIF + CMP ES:[DI.sf_ref_count],sf_busy + JNZ SFNNext ; not marked busy... + fmt TypAccess,LevSFN,<"$p: SFT $x:$x($x)is busy, owner $x:$x\n">, + SaveReg + MOV BX,User_ID + CMP ES:[DI.sf_UID],BX + JNZ SFNNextP + MOV BX,Proc_ID + CMP ES:[DI.sf_PID],BX + JZ SFNGotP +SFNNextP: + fmt TypAccess,LevSFN,<"$p: SFT unusable\n"> + RestoreReg +SFNNext: + INC BX ; no, try next sf number + JMP SFNFreeLoop ; and go until it fails +SFNGot: + SaveReg +SFNGotP: + CLC ; no error + fmt TypAccess,LevSFN,<"$p: SFT $x:$x($x) marked busy\n">, + MOV ES:[DI.sf_ref_count],sf_busy ; make sure that this is allocated + MOV BX,User_ID + MOV ES:[DI.sf_UID],BX + MOV BX,Proc_ID + MOV ES:[DI.sf_PID],BX + RestoreReg +SFNDone: + return ; bye +EndProc SFNFree + +CODE ENDS +END -- cgit v1.2.3