=== Trace listing source: drdos/bin/dosgrps.lst 1 [list -] === Trace listing source: drdos/bin/header.lst 1 ; File : $HEADER.ASM$ 2 ; 3 ; Description : 4 ; 5 ; Original Author : DIGITAL RESEARCH 6 ; 7 ; Last Edited By : $CALDERA$ 8 ; 9 ;-----------------------------------------------------------------------; 10 ; Copyright Work of Caldera, Inc. All Rights Reserved. 11 ; 12 ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, 13 ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. 14 ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES 15 ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF 16 ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO 17 ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE 18 ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE 19 ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, 20 ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, 21 ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, 22 ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF 23 ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT 24 ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND 25 ; CIVIL LIABILITY. 26 ;-----------------------------------------------------------------------; 27 ; 28 ; *** Current Edit History *** 29 ; *** End of Current Edit History *** 30 ; $Log: $ 31 ; HEADER.A86 1.26 94/12/02 09:34:18 32 ; added FCB LRU counter and sharing flag 33 ; HEADER.A86 1.24 94/11/15 08:53:04 34 ; Fixed the NWDOS.386 stuff. Still point at startupinfo, but take out the 35 ; vxdname and the vxdnameseg entries. 36 ; HEADER.A86 1.23 94/06/28 14:31:07 37 ; Fix last_key_ext bug 38 ; HEADER.A86 1.17 93/11/22 15:23:16 39 ; Move idle data to instance page to get per domain idle detection 40 ; HEADER.A86 1.15 93/11/08 19:09:22 41 ; Handle EXEPACK problems even if DOS not in HMA 42 ; HEADER.A86 1.14 93/11/14 18:14:21 43 ; Initialise fdos_buf to 2/0 44 ; HEADER.A86 1.13 93/10/07 19:08:25 45 ; CALL5 always goes through 0:C0 (or FFFF:D0 alias) 46 ; HEADER.A86 1.12 93/09/03 20:28:39 47 ; Add intl/dbcs support for int 21/6523 (query yes/no char) 48 ; HEADER.A86 1.11 93/09/02 22:26:24 49 ; Make uppercase tables compatible (See COMPATIBLE flag in COUNTRY.SYS) 50 ; HEADER.A86 1.9 93/08/10 17:41:25 51 ; Move code fragments for Rolodex Live 52 ; HEADER.A86 1.8 93/08/04 15:15:39 53 ; re-arrange dummy fcbs 54 ; HEADER.A86 1.6 93/07/22 19:29:19 55 ; add no/yes characters 56 ; HEADER.A86 1.5 93/07/20 22:46:33 57 ; dmd_upper_root defaults to FFFF 58 ; ENDLOG 59 ; 60 61 ; DRDOS Header/Initialization Code 62 ; 63 ; NB. 64 ; On a system where the kernel stays low and history is disabled we throw 65 ; away as much code as possible. This includes the patch area, the command 66 ; line history code, and the BDOS initialisation code. 67 ; As we use the patch area the pointer in the header should be incremented 68 ; in order to retain progressively larger amounts of code. 69 70 group PCMDATA PCMODE_DATA FIXED_DOS_DATA PCMODE_CODE BDOS_DATA PCMODE_DSIZE 71 72 group PCMCODE PCM_HEADER PCM_HISTORY PCM_ICODE PCM_CODEND 73 74 [list -] 89 90 PADDING equ 14*1024 ; offset code start by this much 91 92 DOSINROM equ 0800h 93 DOSINHMA equ 1000h 94 95 96 ;**************************************************************************** 97 ; The format of the header is FIXED and should not be modified. 98 ;**************************************************************************** 99 === Switch to base=000000h -> "PCM_HEADER" 100 section PCM_HEADER public align=16 class=CODE 101 102 extrn edit_size:word 103 0 00000000 0038 dw PADDING 0 00000002 000000000000000000 db PADDING-2 dup (0) ; Insert Header 0 0000000B 000000000000000000 0 00000014 000000000000000000 0 0000001D 000000000000000000 0 00000026 000000000000000000 0 0000002F 000000000000000000 0 00000038 000000000000000000 0 00000041 000000000000000000 0 0000004A 000000000000000000 0 00000053 000000000000000000 0 0000005C 000000000000000000 0 00000065 000000000000000000 0 0000006E 000000000000000000 0 00000077 000000000000000000 0 00000080 000000000000000000 0 00000089 000000000000000000 0 00000092 000000000000000000 0 0000009B 000000000000000000 0 000000A4 000000000000000000 0 000000AD 000000000000000000 0 000000B6 000000000000000000 0 000000BF 000000000000000000 0 000000C8 000000000000000000 0 000000D1 000000000000000000 0 000000DA 000000000000000000 0 000000E3 000000000000000000 0 000000EC 000000000000000000 0 000000F5 000000000000000000 0 000000FE 000000000000000000 0 00000107 000000000000000000 0 00000110 000000000000000000 0 00000119 000000000000000000 0 00000122 000000000000000000 0 0000012B 000000000000000000 0 00000134 000000000000000000 0 0000013D 000000000000000000 0 00000146 000000000000000000 0 0000014F 000000000000000000 0 00000158 000000000000000000 0 00000161 000000000000000000 0 0000016A 000000000000000000 0 00000173 000000000000000000 0 0000017C 000000000000000000 0 00000185 000000000000000000 0 0000018E 000000000000000000 0 00000197 000000000000000000 0 000001A0 000000000000000000 0 000001A9 000000000000000000 0 000001B2 000000000000000000 0 000001BB 000000000000000000 0 000001C4 000000000000000000 0 000001CD 000000000000000000 0 000001D6 000000000000000000 0 000001DF 000000000000000000 0 000001E8 000000000000000000 0 000001F1 000000000000000000 0 000001FA 000000000000000000 0 00000203 000000000000000000 0 0000020C 000000000000000000 0 00000215 000000000000000000 0 0000021E 000000000000000000 0 00000227 000000000000000000 0 00000230 000000000000000000 0 00000239 000000000000000000 0 00000242 000000000000000000 0 0000024B 000000000000000000 0 00000254 000000000000000000 0 0000025D 000000000000000000 0 00000266 000000000000000000 0 0000026F 000000000000000000 0 00000278 000000000000000000 0 00000281 000000000000000000 0 0000028A 000000000000000000 0 00000293 000000000000000000 0 0000029C 000000000000000000 0 000002A5 000000000000000000 0 000002AE 000000000000000000 0 000002B7 000000000000000000 0 000002C0 000000000000000000 0 000002C9 000000000000000000 0 000002D2 000000000000000000 0 000002DB 000000000000000000 0 000002E4 000000000000000000 0 000002ED 000000000000000000 0 000002F6 000000000000000000 0 000002FF 000000000000000000 0 00000308 000000000000000000 0 00000311 000000000000000000 0 0000031A 000000000000000000 0 00000323 000000000000000000 0 0000032C 000000000000000000 0 00000335 000000000000000000 0 0000033E 000000000000000000 0 00000347 000000000000000000 0 00000350 000000000000000000 0 00000359 000000000000000000 0 00000362 000000000000000000 0 0000036B 000000000000000000 0 00000374 000000000000000000 0 0000037D 000000000000000000 0 00000386 000000000000000000 0 0000038F 000000000000000000 0 00000398 000000000000000000 0 000003A1 000000000000000000 0 000003AA 000000000000000000 0 000003B3 000000000000000000 0 000003BC 000000000000000000 0 000003C5 000000000000000000 0 000003CE 000000000000000000 0 000003D7 000000000000000000 0 000003E0 000000000000000000 0 000003E9 000000000000000000 0 000003F2 000000000000000000 0 000003FB 000000000000000000 0 00000404 000000000000000000 0 0000040D 000000000000000000 0 00000416 000000000000000000 0 0000041F 000000000000000000 0 00000428 000000000000000000 0 00000431 000000000000000000 0 0000043A 000000000000000000 0 00000443 000000000000000000 0 0000044C 000000000000000000 0 00000455 000000000000000000 0 0000045E 000000000000000000 0 00000467 000000000000000000 0 00000470 000000000000000000 0 00000479 000000000000000000 0 00000482 000000000000000000 0 0000048B 000000000000000000 0 00000494 000000000000000000 0 0000049D 000000000000000000 0 000004A6 000000000000000000 0 000004AF 000000000000000000 0 000004B8 000000000000000000 0 000004C1 000000000000000000 0 000004CA 000000000000000000 0 000004D3 000000000000000000 0 000004DC 000000000000000000 0 000004E5 000000000000000000 0 000004EE 000000000000000000 0 000004F7 000000000000000000 0 00000500 000000000000000000 0 00000509 000000000000000000 0 00000512 000000000000000000 0 0000051B 000000000000000000 0 00000524 000000000000000000 0 0000052D 000000000000000000 0 00000536 000000000000000000 0 0000053F 000000000000000000 0 00000548 000000000000000000 0 00000551 000000000000000000 0 0000055A 000000000000000000 0 00000563 000000000000000000 0 0000056C 000000000000000000 0 00000575 000000000000000000 0 0000057E 000000000000000000 0 00000587 000000000000000000 0 00000590 000000000000000000 0 00000599 000000000000000000 0 000005A2 000000000000000000 0 000005AB 000000000000000000 0 000005B4 000000000000000000 0 000005BD 000000000000000000 0 000005C6 000000000000000000 0 000005CF 000000000000000000 0 000005D8 000000000000000000 0 000005E1 000000000000000000 0 000005EA 000000000000000000 0 000005F3 000000000000000000 0 000005FC 000000000000000000 0 00000605 000000000000000000 0 0000060E 000000000000000000 0 00000617 000000000000000000 0 00000620 000000000000000000 0 00000629 000000000000000000 0 00000632 000000000000000000 0 0000063B 000000000000000000 0 00000644 000000000000000000 0 0000064D 000000000000000000 0 00000656 000000000000000000 0 0000065F 000000000000000000 0 00000668 000000000000000000 0 00000671 000000000000000000 0 0000067A 000000000000000000 0 00000683 000000000000000000 0 0000068C 000000000000000000 0 00000695 000000000000000000 0 0000069E 000000000000000000 0 000006A7 000000000000000000 0 000006B0 000000000000000000 0 000006B9 000000000000000000 0 000006C2 000000000000000000 0 000006CB 000000000000000000 0 000006D4 000000000000000000 0 000006DD 000000000000000000 0 000006E6 000000000000000000 0 000006EF 000000000000000000 0 000006F8 000000000000000000 0 00000701 000000000000000000 0 0000070A 000000000000000000 0 00000713 000000000000000000 0 0000071C 000000000000000000 0 00000725 000000000000000000 0 0000072E 000000000000000000 0 00000737 000000000000000000 0 00000740 000000000000000000 0 00000749 000000000000000000 0 00000752 000000000000000000 0 0000075B 000000000000000000 0 00000764 000000000000000000 0 0000076D 000000000000000000 0 00000776 000000000000000000 0 0000077F 000000000000000000 0 00000788 000000000000000000 0 00000791 000000000000000000 0 0000079A 000000000000000000 0 000007A3 000000000000000000 0 000007AC 000000000000000000 0 000007B5 000000000000000000 0 000007BE 000000000000000000 0 000007C7 000000000000000000 0 000007D0 000000000000000000 0 000007D9 000000000000000000 0 000007E2 000000000000000000 0 000007EB 000000000000000000 0 000007F4 000000000000000000 0 000007FD 000000000000000000 0 00000806 000000000000000000 0 0000080F 000000000000000000 0 00000818 000000000000000000 0 00000821 000000000000000000 0 0000082A 000000000000000000 0 00000833 000000000000000000 0 0000083C 000000000000000000 0 00000845 000000000000000000 0 0000084E 000000000000000000 0 00000857 000000000000000000 0 00000860 000000000000000000 0 00000869 000000000000000000 0 00000872 000000000000000000 0 0000087B 000000000000000000 0 00000884 000000000000000000 0 0000088D 000000000000000000 0 00000896 000000000000000000 0 0000089F 000000000000000000 0 000008A8 000000000000000000 0 000008B1 000000000000000000 0 000008BA 000000000000000000 0 000008C3 000000000000000000 0 000008CC 000000000000000000 0 000008D5 000000000000000000 0 000008DE 000000000000000000 0 000008E7 000000000000000000 0 000008F0 000000000000000000 0 000008F9 000000000000000000 0 00000902 000000000000000000 0 0000090B 000000000000000000 0 00000914 000000000000000000 0 0000091D 000000000000000000 0 00000926 000000000000000000 0 0000092F 000000000000000000 0 00000938 000000000000000000 0 00000941 000000000000000000 0 0000094A 000000000000000000 0 00000953 000000000000000000 0 0000095C 000000000000000000 0 00000965 000000000000000000 0 0000096E 000000000000000000 0 00000977 000000000000000000 0 00000980 000000000000000000 0 00000989 000000000000000000 0 00000992 000000000000000000 0 0000099B 000000000000000000 0 000009A4 000000000000000000 0 000009AD 000000000000000000 0 000009B6 000000000000000000 0 000009BF 000000000000000000 0 000009C8 000000000000000000 0 000009D1 000000000000000000 0 000009DA 000000000000000000 0 000009E3 000000000000000000 0 000009EC 000000000000000000 0 000009F5 000000000000000000 0 000009FE 000000000000000000 0 00000A07 000000000000000000 0 00000A10 000000000000000000 0 00000A19 000000000000000000 0 00000A22 000000000000000000 0 00000A2B 000000000000000000 0 00000A34 000000000000000000 0 00000A3D 000000000000000000 0 00000A46 000000000000000000 0 00000A4F 000000000000000000 0 00000A58 000000000000000000 0 00000A61 000000000000000000 0 00000A6A 000000000000000000 0 00000A73 000000000000000000 0 00000A7C 000000000000000000 0 00000A85 000000000000000000 0 00000A8E 000000000000000000 0 00000A97 000000000000000000 0 00000AA0 000000000000000000 0 00000AA9 000000000000000000 0 00000AB2 000000000000000000 0 00000ABB 000000000000000000 0 00000AC4 000000000000000000 0 00000ACD 000000000000000000 0 00000AD6 000000000000000000 0 00000ADF 000000000000000000 0 00000AE8 000000000000000000 0 00000AF1 000000000000000000 0 00000AFA 000000000000000000 0 00000B03 000000000000000000 0 00000B0C 000000000000000000 0 00000B15 000000000000000000 0 00000B1E 000000000000000000 0 00000B27 000000000000000000 0 00000B30 000000000000000000 0 00000B39 000000000000000000 0 00000B42 000000000000000000 0 00000B4B 000000000000000000 0 00000B54 000000000000000000 0 00000B5D 000000000000000000 0 00000B66 000000000000000000 0 00000B6F 000000000000000000 0 00000B78 000000000000000000 0 00000B81 000000000000000000 0 00000B8A 000000000000000000 0 00000B93 000000000000000000 0 00000B9C 000000000000000000 0 00000BA5 000000000000000000 0 00000BAE 000000000000000000 0 00000BB7 000000000000000000 0 00000BC0 000000000000000000 0 00000BC9 000000000000000000 0 00000BD2 000000000000000000 0 00000BDB 000000000000000000 0 00000BE4 000000000000000000 0 00000BED 000000000000000000 0 00000BF6 000000000000000000 0 00000BFF 000000000000000000 0 00000C08 000000000000000000 0 00000C11 000000000000000000 0 00000C1A 000000000000000000 0 00000C23 000000000000000000 0 00000C2C 000000000000000000 0 00000C35 000000000000000000 0 00000C3E 000000000000000000 0 00000C47 000000000000000000 0 00000C50 000000000000000000 0 00000C59 000000000000000000 0 00000C62 000000000000000000 0 00000C6B 000000000000000000 0 00000C74 000000000000000000 0 00000C7D 000000000000000000 0 00000C86 000000000000000000 0 00000C8F 000000000000000000 0 00000C98 000000000000000000 0 00000CA1 000000000000000000 0 00000CAA 000000000000000000 0 00000CB3 000000000000000000 0 00000CBC 000000000000000000 0 00000CC5 000000000000000000 0 00000CCE 000000000000000000 0 00000CD7 000000000000000000 0 00000CE0 000000000000000000 0 00000CE9 000000000000000000 0 00000CF2 000000000000000000 0 00000CFB 000000000000000000 0 00000D04 000000000000000000 0 00000D0D 000000000000000000 0 00000D16 000000000000000000 0 00000D1F 000000000000000000 0 00000D28 000000000000000000 0 00000D31 000000000000000000 0 00000D3A 000000000000000000 0 00000D43 000000000000000000 0 00000D4C 000000000000000000 0 00000D55 000000000000000000 0 00000D5E 000000000000000000 0 00000D67 000000000000000000 0 00000D70 000000000000000000 0 00000D79 000000000000000000 0 00000D82 000000000000000000 0 00000D8B 000000000000000000 0 00000D94 000000000000000000 0 00000D9D 000000000000000000 0 00000DA6 000000000000000000 0 00000DAF 000000000000000000 0 00000DB8 000000000000000000 0 00000DC1 000000000000000000 0 00000DCA 000000000000000000 0 00000DD3 000000000000000000 0 00000DDC 000000000000000000 0 00000DE5 000000000000000000 0 00000DEE 000000000000000000 0 00000DF7 000000000000000000 0 00000E00 000000000000000000 0 00000E09 000000000000000000 0 00000E12 000000000000000000 0 00000E1B 000000000000000000 0 00000E24 000000000000000000 0 00000E2D 000000000000000000 0 00000E36 000000000000000000 0 00000E3F 000000000000000000 0 00000E48 000000000000000000 0 00000E51 000000000000000000 0 00000E5A 000000000000000000 0 00000E63 000000000000000000 0 00000E6C 000000000000000000 0 00000E75 000000000000000000 0 00000E7E 000000000000000000 0 00000E87 000000000000000000 0 00000E90 000000000000000000 0 00000E99 000000000000000000 0 00000EA2 000000000000000000 0 00000EAB 000000000000000000 0 00000EB4 000000000000000000 0 00000EBD 000000000000000000 0 00000EC6 000000000000000000 0 00000ECF 000000000000000000 0 00000ED8 000000000000000000 0 00000EE1 000000000000000000 0 00000EEA 000000000000000000 0 00000EF3 000000000000000000 0 00000EFC 000000000000000000 0 00000F05 000000000000000000 0 00000F0E 000000000000000000 0 00000F17 000000000000000000 0 00000F20 000000000000000000 0 00000F29 000000000000000000 0 00000F32 000000000000000000 0 00000F3B 000000000000000000 0 00000F44 000000000000000000 0 00000F4D 000000000000000000 0 00000F56 000000000000000000 0 00000F5F 000000000000000000 0 00000F68 000000000000000000 0 00000F71 000000000000000000 0 00000F7A 000000000000000000 0 00000F83 000000000000000000 0 00000F8C 000000000000000000 0 00000F95 000000000000000000 0 00000F9E 000000000000000000 0 00000FA7 000000000000000000 0 00000FB0 000000000000000000 0 00000FB9 000000000000000000 0 00000FC2 000000000000000000 0 00000FCB 000000000000000000 0 00000FD4 000000000000000000 0 00000FDD 000000000000000000 0 00000FE6 000000000000000000 0 00000FEF 000000000000000000 0 00000FF8 000000000000000000 0 00001001 000000000000000000 0 0000100A 000000000000000000 0 00001013 000000000000000000 0 0000101C 000000000000000000 0 00001025 000000000000000000 0 0000102E 000000000000000000 0 00001037 000000000000000000 0 00001040 000000000000000000 0 00001049 000000000000000000 0 00001052 000000000000000000 0 0000105B 000000000000000000 0 00001064 000000000000000000 0 0000106D 000000000000000000 0 00001076 000000000000000000 0 0000107F 000000000000000000 0 00001088 000000000000000000 0 00001091 000000000000000000 0 0000109A 000000000000000000 0 000010A3 000000000000000000 0 000010AC 000000000000000000 0 000010B5 000000000000000000 0 000010BE 000000000000000000 0 000010C7 000000000000000000 0 000010D0 000000000000000000 0 000010D9 000000000000000000 0 000010E2 000000000000000000 0 000010EB 000000000000000000 0 000010F4 000000000000000000 0 000010FD 000000000000000000 0 00001106 000000000000000000 0 0000110F 000000000000000000 0 00001118 000000000000000000 0 00001121 000000000000000000 0 0000112A 000000000000000000 0 00001133 000000000000000000 0 0000113C 000000000000000000 0 00001145 000000000000000000 0 0000114E 000000000000000000 0 00001157 000000000000000000 0 00001160 000000000000000000 0 00001169 000000000000000000 0 00001172 000000000000000000 0 0000117B 000000000000000000 0 00001184 000000000000000000 0 0000118D 000000000000000000 0 00001196 000000000000000000 0 0000119F 000000000000000000 0 000011A8 000000000000000000 0 000011B1 000000000000000000 0 000011BA 000000000000000000 0 000011C3 000000000000000000 0 000011CC 000000000000000000 0 000011D5 000000000000000000 0 000011DE 000000000000000000 0 000011E7 000000000000000000 0 000011F0 000000000000000000 0 000011F9 000000000000000000 0 00001202 000000000000000000 0 0000120B 000000000000000000 0 00001214 000000000000000000 0 0000121D 000000000000000000 0 00001226 000000000000000000 0 0000122F 000000000000000000 0 00001238 000000000000000000 0 00001241 000000000000000000 0 0000124A 000000000000000000 0 00001253 000000000000000000 0 0000125C 000000000000000000 0 00001265 000000000000000000 0 0000126E 000000000000000000 0 00001277 000000000000000000 0 00001280 000000000000000000 0 00001289 000000000000000000 0 00001292 000000000000000000 0 0000129B 000000000000000000 0 000012A4 000000000000000000 0 000012AD 000000000000000000 0 000012B6 000000000000000000 0 000012BF 000000000000000000 0 000012C8 000000000000000000 0 000012D1 000000000000000000 0 000012DA 000000000000000000 0 000012E3 000000000000000000 0 000012EC 000000000000000000 0 000012F5 000000000000000000 0 000012FE 000000000000000000 0 00001307 000000000000000000 0 00001310 000000000000000000 0 00001319 000000000000000000 0 00001322 000000000000000000 0 0000132B 000000000000000000 0 00001334 000000000000000000 0 0000133D 000000000000000000 0 00001346 000000000000000000 0 0000134F 000000000000000000 0 00001358 000000000000000000 0 00001361 000000000000000000 0 0000136A 000000000000000000 0 00001373 000000000000000000 0 0000137C 000000000000000000 0 00001385 000000000000000000 0 0000138E 000000000000000000 0 00001397 000000000000000000 0 000013A0 000000000000000000 0 000013A9 000000000000000000 0 000013B2 000000000000000000 0 000013BB 000000000000000000 0 000013C4 000000000000000000 0 000013CD 000000000000000000 0 000013D6 000000000000000000 0 000013DF 000000000000000000 0 000013E8 000000000000000000 0 000013F1 000000000000000000 0 000013FA 000000000000000000 0 00001403 000000000000000000 0 0000140C 000000000000000000 0 00001415 000000000000000000 0 0000141E 000000000000000000 0 00001427 000000000000000000 0 00001430 000000000000000000 0 00001439 000000000000000000 0 00001442 000000000000000000 0 0000144B 000000000000000000 0 00001454 000000000000000000 0 0000145D 000000000000000000 0 00001466 000000000000000000 0 0000146F 000000000000000000 0 00001478 000000000000000000 0 00001481 000000000000000000 0 0000148A 000000000000000000 0 00001493 000000000000000000 0 0000149C 000000000000000000 0 000014A5 000000000000000000 0 000014AE 000000000000000000 0 000014B7 000000000000000000 0 000014C0 000000000000000000 0 000014C9 000000000000000000 0 000014D2 000000000000000000 0 000014DB 000000000000000000 0 000014E4 000000000000000000 0 000014ED 000000000000000000 0 000014F6 000000000000000000 0 000014FF 000000000000000000 0 00001508 000000000000000000 0 00001511 000000000000000000 0 0000151A 000000000000000000 0 00001523 000000000000000000 0 0000152C 000000000000000000 0 00001535 000000000000000000 0 0000153E 000000000000000000 0 00001547 000000000000000000 0 00001550 000000000000000000 0 00001559 000000000000000000 0 00001562 000000000000000000 0 0000156B 000000000000000000 0 00001574 000000000000000000 0 0000157D 000000000000000000 0 00001586 000000000000000000 0 0000158F 000000000000000000 0 00001598 000000000000000000 0 000015A1 000000000000000000 0 000015AA 000000000000000000 0 000015B3 000000000000000000 0 000015BC 000000000000000000 0 000015C5 000000000000000000 0 000015CE 000000000000000000 0 000015D7 000000000000000000 0 000015E0 000000000000000000 0 000015E9 000000000000000000 0 000015F2 000000000000000000 0 000015FB 000000000000000000 0 00001604 000000000000000000 0 0000160D 000000000000000000 0 00001616 000000000000000000 0 0000161F 000000000000000000 0 00001628 000000000000000000 0 00001631 000000000000000000 0 0000163A 000000000000000000 0 00001643 000000000000000000 0 0000164C 000000000000000000 0 00001655 000000000000000000 0 0000165E 000000000000000000 0 00001667 000000000000000000 0 00001670 000000000000000000 0 00001679 000000000000000000 0 00001682 000000000000000000 0 0000168B 000000000000000000 0 00001694 000000000000000000 0 0000169D 000000000000000000 0 000016A6 000000000000000000 0 000016AF 000000000000000000 0 000016B8 000000000000000000 0 000016C1 000000000000000000 0 000016CA 000000000000000000 0 000016D3 000000000000000000 0 000016DC 000000000000000000 0 000016E5 000000000000000000 0 000016EE 000000000000000000 0 000016F7 000000000000000000 0 00001700 000000000000000000 0 00001709 000000000000000000 0 00001712 000000000000000000 0 0000171B 000000000000000000 0 00001724 000000000000000000 0 0000172D 000000000000000000 0 00001736 000000000000000000 0 0000173F 000000000000000000 0 00001748 000000000000000000 0 00001751 000000000000000000 0 0000175A 000000000000000000 0 00001763 000000000000000000 0 0000176C 000000000000000000 0 00001775 000000000000000000 0 0000177E 000000000000000000 0 00001787 000000000000000000 0 00001790 000000000000000000 0 00001799 000000000000000000 0 000017A2 000000000000000000 0 000017AB 000000000000000000 0 000017B4 000000000000000000 0 000017BD 000000000000000000 0 000017C6 000000000000000000 0 000017CF 000000000000000000 0 000017D8 000000000000000000 0 000017E1 000000000000000000 0 000017EA 000000000000000000 0 000017F3 000000000000000000 0 000017FC 000000000000000000 0 00001805 000000000000000000 0 0000180E 000000000000000000 0 00001817 000000000000000000 0 00001820 000000000000000000 0 00001829 000000000000000000 0 00001832 000000000000000000 0 0000183B 000000000000000000 0 00001844 000000000000000000 0 0000184D 000000000000000000 0 00001856 000000000000000000 0 0000185F 000000000000000000 0 00001868 000000000000000000 0 00001871 000000000000000000 0 0000187A 000000000000000000 0 00001883 000000000000000000 0 0000188C 000000000000000000 0 00001895 000000000000000000 0 0000189E 000000000000000000 0 000018A7 000000000000000000 0 000018B0 000000000000000000 0 000018B9 000000000000000000 0 000018C2 000000000000000000 0 000018CB 000000000000000000 0 000018D4 000000000000000000 0 000018DD 000000000000000000 0 000018E6 000000000000000000 0 000018EF 000000000000000000 0 000018F8 000000000000000000 0 00001901 000000000000000000 0 0000190A 000000000000000000 0 00001913 000000000000000000 0 0000191C 000000000000000000 0 00001925 000000000000000000 0 0000192E 000000000000000000 0 00001937 000000000000000000 0 00001940 000000000000000000 0 00001949 000000000000000000 0 00001952 000000000000000000 0 0000195B 000000000000000000 0 00001964 000000000000000000 0 0000196D 000000000000000000 0 00001976 000000000000000000 0 0000197F 000000000000000000 0 00001988 000000000000000000 0 00001991 000000000000000000 0 0000199A 000000000000000000 0 000019A3 000000000000000000 0 000019AC 000000000000000000 0 000019B5 000000000000000000 0 000019BE 000000000000000000 0 000019C7 000000000000000000 0 000019D0 000000000000000000 0 000019D9 000000000000000000 0 000019E2 000000000000000000 0 000019EB 000000000000000000 0 000019F4 000000000000000000 0 000019FD 000000000000000000 0 00001A06 000000000000000000 0 00001A0F 000000000000000000 0 00001A18 000000000000000000 0 00001A21 000000000000000000 0 00001A2A 000000000000000000 0 00001A33 000000000000000000 0 00001A3C 000000000000000000 0 00001A45 000000000000000000 0 00001A4E 000000000000000000 0 00001A57 000000000000000000 0 00001A60 000000000000000000 0 00001A69 000000000000000000 0 00001A72 000000000000000000 0 00001A7B 000000000000000000 0 00001A84 000000000000000000 0 00001A8D 000000000000000000 0 00001A96 000000000000000000 0 00001A9F 000000000000000000 0 00001AA8 000000000000000000 0 00001AB1 000000000000000000 0 00001ABA 000000000000000000 0 00001AC3 000000000000000000 0 00001ACC 000000000000000000 0 00001AD5 000000000000000000 0 00001ADE 000000000000000000 0 00001AE7 000000000000000000 0 00001AF0 000000000000000000 0 00001AF9 000000000000000000 0 00001B02 000000000000000000 0 00001B0B 000000000000000000 0 00001B14 000000000000000000 0 00001B1D 000000000000000000 0 00001B26 000000000000000000 0 00001B2F 000000000000000000 0 00001B38 000000000000000000 0 00001B41 000000000000000000 0 00001B4A 000000000000000000 0 00001B53 000000000000000000 0 00001B5C 000000000000000000 0 00001B65 000000000000000000 0 00001B6E 000000000000000000 0 00001B77 000000000000000000 0 00001B80 000000000000000000 0 00001B89 000000000000000000 0 00001B92 000000000000000000 0 00001B9B 000000000000000000 0 00001BA4 000000000000000000 0 00001BAD 000000000000000000 0 00001BB6 000000000000000000 0 00001BBF 000000000000000000 0 00001BC8 000000000000000000 0 00001BD1 000000000000000000 0 00001BDA 000000000000000000 0 00001BE3 000000000000000000 0 00001BEC 000000000000000000 0 00001BF5 000000000000000000 0 00001BFE 000000000000000000 0 00001C07 000000000000000000 0 00001C10 000000000000000000 0 00001C19 000000000000000000 0 00001C22 000000000000000000 0 00001C2B 000000000000000000 0 00001C34 000000000000000000 0 00001C3D 000000000000000000 0 00001C46 000000000000000000 0 00001C4F 000000000000000000 0 00001C58 000000000000000000 0 00001C61 000000000000000000 0 00001C6A 000000000000000000 0 00001C73 000000000000000000 0 00001C7C 000000000000000000 0 00001C85 000000000000000000 0 00001C8E 000000000000000000 0 00001C97 000000000000000000 0 00001CA0 000000000000000000 0 00001CA9 000000000000000000 0 00001CB2 000000000000000000 0 00001CBB 000000000000000000 0 00001CC4 000000000000000000 0 00001CCD 000000000000000000 0 00001CD6 000000000000000000 0 00001CDF 000000000000000000 0 00001CE8 000000000000000000 0 00001CF1 000000000000000000 0 00001CFA 000000000000000000 0 00001D03 000000000000000000 0 00001D0C 000000000000000000 0 00001D15 000000000000000000 0 00001D1E 000000000000000000 0 00001D27 000000000000000000 0 00001D30 000000000000000000 0 00001D39 000000000000000000 0 00001D42 000000000000000000 0 00001D4B 000000000000000000 0 00001D54 000000000000000000 0 00001D5D 000000000000000000 0 00001D66 000000000000000000 0 00001D6F 000000000000000000 0 00001D78 000000000000000000 0 00001D81 000000000000000000 0 00001D8A 000000000000000000 0 00001D93 000000000000000000 0 00001D9C 000000000000000000 0 00001DA5 000000000000000000 0 00001DAE 000000000000000000 0 00001DB7 000000000000000000 0 00001DC0 000000000000000000 0 00001DC9 000000000000000000 0 00001DD2 000000000000000000 0 00001DDB 000000000000000000 0 00001DE4 000000000000000000 0 00001DED 000000000000000000 0 00001DF6 000000000000000000 0 00001DFF 000000000000000000 0 00001E08 000000000000000000 0 00001E11 000000000000000000 0 00001E1A 000000000000000000 0 00001E23 000000000000000000 0 00001E2C 000000000000000000 0 00001E35 000000000000000000 0 00001E3E 000000000000000000 0 00001E47 000000000000000000 0 00001E50 000000000000000000 0 00001E59 000000000000000000 0 00001E62 000000000000000000 0 00001E6B 000000000000000000 0 00001E74 000000000000000000 0 00001E7D 000000000000000000 0 00001E86 000000000000000000 0 00001E8F 000000000000000000 0 00001E98 000000000000000000 0 00001EA1 000000000000000000 0 00001EAA 000000000000000000 0 00001EB3 000000000000000000 0 00001EBC 000000000000000000 0 00001EC5 000000000000000000 0 00001ECE 000000000000000000 0 00001ED7 000000000000000000 0 00001EE0 000000000000000000 0 00001EE9 000000000000000000 0 00001EF2 000000000000000000 0 00001EFB 000000000000000000 0 00001F04 000000000000000000 0 00001F0D 000000000000000000 0 00001F16 000000000000000000 0 00001F1F 000000000000000000 0 00001F28 000000000000000000 0 00001F31 000000000000000000 0 00001F3A 000000000000000000 0 00001F43 000000000000000000 0 00001F4C 000000000000000000 0 00001F55 000000000000000000 0 00001F5E 000000000000000000 0 00001F67 000000000000000000 0 00001F70 000000000000000000 0 00001F79 000000000000000000 0 00001F82 000000000000000000 0 00001F8B 000000000000000000 0 00001F94 000000000000000000 0 00001F9D 000000000000000000 0 00001FA6 000000000000000000 0 00001FAF 000000000000000000 0 00001FB8 000000000000000000 0 00001FC1 000000000000000000 0 00001FCA 000000000000000000 0 00001FD3 000000000000000000 0 00001FDC 000000000000000000 0 00001FE5 000000000000000000 0 00001FEE 000000000000000000 0 00001FF7 000000000000000000 0 00002000 000000000000000000 0 00002009 000000000000000000 0 00002012 000000000000000000 0 0000201B 000000000000000000 0 00002024 000000000000000000 0 0000202D 000000000000000000 0 00002036 000000000000000000 0 0000203F 000000000000000000 0 00002048 000000000000000000 0 00002051 000000000000000000 0 0000205A 000000000000000000 0 00002063 000000000000000000 0 0000206C 000000000000000000 0 00002075 000000000000000000 0 0000207E 000000000000000000 0 00002087 000000000000000000 0 00002090 000000000000000000 0 00002099 000000000000000000 0 000020A2 000000000000000000 0 000020AB 000000000000000000 0 000020B4 000000000000000000 0 000020BD 000000000000000000 0 000020C6 000000000000000000 0 000020CF 000000000000000000 0 000020D8 000000000000000000 0 000020E1 000000000000000000 0 000020EA 000000000000000000 0 000020F3 000000000000000000 0 000020FC 000000000000000000 0 00002105 000000000000000000 0 0000210E 000000000000000000 0 00002117 000000000000000000 0 00002120 000000000000000000 0 00002129 000000000000000000 0 00002132 000000000000000000 0 0000213B 000000000000000000 0 00002144 000000000000000000 0 0000214D 000000000000000000 0 00002156 000000000000000000 0 0000215F 000000000000000000 0 00002168 000000000000000000 0 00002171 000000000000000000 0 0000217A 000000000000000000 0 00002183 000000000000000000 0 0000218C 000000000000000000 0 00002195 000000000000000000 0 0000219E 000000000000000000 0 000021A7 000000000000000000 0 000021B0 000000000000000000 0 000021B9 000000000000000000 0 000021C2 000000000000000000 0 000021CB 000000000000000000 0 000021D4 000000000000000000 0 000021DD 000000000000000000 0 000021E6 000000000000000000 0 000021EF 000000000000000000 0 000021F8 000000000000000000 0 00002201 000000000000000000 0 0000220A 000000000000000000 0 00002213 000000000000000000 0 0000221C 000000000000000000 0 00002225 000000000000000000 0 0000222E 000000000000000000 0 00002237 000000000000000000 0 00002240 000000000000000000 0 00002249 000000000000000000 0 00002252 000000000000000000 0 0000225B 000000000000000000 0 00002264 000000000000000000 0 0000226D 000000000000000000 0 00002276 000000000000000000 0 0000227F 000000000000000000 0 00002288 000000000000000000 0 00002291 000000000000000000 0 0000229A 000000000000000000 0 000022A3 000000000000000000 0 000022AC 000000000000000000 0 000022B5 000000000000000000 0 000022BE 000000000000000000 0 000022C7 000000000000000000 0 000022D0 000000000000000000 0 000022D9 000000000000000000 0 000022E2 000000000000000000 0 000022EB 000000000000000000 0 000022F4 000000000000000000 0 000022FD 000000000000000000 0 00002306 000000000000000000 0 0000230F 000000000000000000 0 00002318 000000000000000000 0 00002321 000000000000000000 0 0000232A 000000000000000000 0 00002333 000000000000000000 0 0000233C 000000000000000000 0 00002345 000000000000000000 0 0000234E 000000000000000000 0 00002357 000000000000000000 0 00002360 000000000000000000 0 00002369 000000000000000000 0 00002372 000000000000000000 0 0000237B 000000000000000000 0 00002384 000000000000000000 0 0000238D 000000000000000000 0 00002396 000000000000000000 0 0000239F 000000000000000000 0 000023A8 000000000000000000 0 000023B1 000000000000000000 0 000023BA 000000000000000000 0 000023C3 000000000000000000 0 000023CC 000000000000000000 0 000023D5 000000000000000000 0 000023DE 000000000000000000 0 000023E7 000000000000000000 0 000023F0 000000000000000000 0 000023F9 000000000000000000 0 00002402 000000000000000000 0 0000240B 000000000000000000 0 00002414 000000000000000000 0 0000241D 000000000000000000 0 00002426 000000000000000000 0 0000242F 000000000000000000 0 00002438 000000000000000000 0 00002441 000000000000000000 0 0000244A 000000000000000000 0 00002453 000000000000000000 0 0000245C 000000000000000000 0 00002465 000000000000000000 0 0000246E 000000000000000000 0 00002477 000000000000000000 0 00002480 000000000000000000 0 00002489 000000000000000000 0 00002492 000000000000000000 0 0000249B 000000000000000000 0 000024A4 000000000000000000 0 000024AD 000000000000000000 0 000024B6 000000000000000000 0 000024BF 000000000000000000 0 000024C8 000000000000000000 0 000024D1 000000000000000000 0 000024DA 000000000000000000 0 000024E3 000000000000000000 0 000024EC 000000000000000000 0 000024F5 000000000000000000 0 000024FE 000000000000000000 0 00002507 000000000000000000 0 00002510 000000000000000000 0 00002519 000000000000000000 0 00002522 000000000000000000 0 0000252B 000000000000000000 0 00002534 000000000000000000 0 0000253D 000000000000000000 0 00002546 000000000000000000 0 0000254F 000000000000000000 0 00002558 000000000000000000 0 00002561 000000000000000000 0 0000256A 000000000000000000 0 00002573 000000000000000000 0 0000257C 000000000000000000 0 00002585 000000000000000000 0 0000258E 000000000000000000 0 00002597 000000000000000000 0 000025A0 000000000000000000 0 000025A9 000000000000000000 0 000025B2 000000000000000000 0 000025BB 000000000000000000 0 000025C4 000000000000000000 0 000025CD 000000000000000000 0 000025D6 000000000000000000 0 000025DF 000000000000000000 0 000025E8 000000000000000000 0 000025F1 000000000000000000 0 000025FA 000000000000000000 0 00002603 000000000000000000 0 0000260C 000000000000000000 0 00002615 000000000000000000 0 0000261E 000000000000000000 0 00002627 000000000000000000 0 00002630 000000000000000000 0 00002639 000000000000000000 0 00002642 000000000000000000 0 0000264B 000000000000000000 0 00002654 000000000000000000 0 0000265D 000000000000000000 0 00002666 000000000000000000 0 0000266F 000000000000000000 0 00002678 000000000000000000 0 00002681 000000000000000000 0 0000268A 000000000000000000 0 00002693 000000000000000000 0 0000269C 000000000000000000 0 000026A5 000000000000000000 0 000026AE 000000000000000000 0 000026B7 000000000000000000 0 000026C0 000000000000000000 0 000026C9 000000000000000000 0 000026D2 000000000000000000 0 000026DB 000000000000000000 0 000026E4 000000000000000000 0 000026ED 000000000000000000 0 000026F6 000000000000000000 0 000026FF 000000000000000000 0 00002708 000000000000000000 0 00002711 000000000000000000 0 0000271A 000000000000000000 0 00002723 000000000000000000 0 0000272C 000000000000000000 0 00002735 000000000000000000 0 0000273E 000000000000000000 0 00002747 000000000000000000 0 00002750 000000000000000000 0 00002759 000000000000000000 0 00002762 000000000000000000 0 0000276B 000000000000000000 0 00002774 000000000000000000 0 0000277D 000000000000000000 0 00002786 000000000000000000 0 0000278F 000000000000000000 0 00002798 000000000000000000 0 000027A1 000000000000000000 0 000027AA 000000000000000000 0 000027B3 000000000000000000 0 000027BC 000000000000000000 0 000027C5 000000000000000000 0 000027CE 000000000000000000 0 000027D7 000000000000000000 0 000027E0 000000000000000000 0 000027E9 000000000000000000 0 000027F2 000000000000000000 0 000027FB 000000000000000000 0 00002804 000000000000000000 0 0000280D 000000000000000000 0 00002816 000000000000000000 0 0000281F 000000000000000000 0 00002828 000000000000000000 0 00002831 000000000000000000 0 0000283A 000000000000000000 0 00002843 000000000000000000 0 0000284C 000000000000000000 0 00002855 000000000000000000 0 0000285E 000000000000000000 0 00002867 000000000000000000 0 00002870 000000000000000000 0 00002879 000000000000000000 0 00002882 000000000000000000 0 0000288B 000000000000000000 0 00002894 000000000000000000 0 0000289D 000000000000000000 0 000028A6 000000000000000000 0 000028AF 000000000000000000 0 000028B8 000000000000000000 0 000028C1 000000000000000000 0 000028CA 000000000000000000 0 000028D3 000000000000000000 0 000028DC 000000000000000000 0 000028E5 000000000000000000 0 000028EE 000000000000000000 0 000028F7 000000000000000000 0 00002900 000000000000000000 0 00002909 000000000000000000 0 00002912 000000000000000000 0 0000291B 000000000000000000 0 00002924 000000000000000000 0 0000292D 000000000000000000 0 00002936 000000000000000000 0 0000293F 000000000000000000 0 00002948 000000000000000000 0 00002951 000000000000000000 0 0000295A 000000000000000000 0 00002963 000000000000000000 0 0000296C 000000000000000000 0 00002975 000000000000000000 0 0000297E 000000000000000000 0 00002987 000000000000000000 0 00002990 000000000000000000 0 00002999 000000000000000000 0 000029A2 000000000000000000 0 000029AB 000000000000000000 0 000029B4 000000000000000000 0 000029BD 000000000000000000 0 000029C6 000000000000000000 0 000029CF 000000000000000000 0 000029D8 000000000000000000 0 000029E1 000000000000000000 0 000029EA 000000000000000000 0 000029F3 000000000000000000 0 000029FC 000000000000000000 0 00002A05 000000000000000000 0 00002A0E 000000000000000000 0 00002A17 000000000000000000 0 00002A20 000000000000000000 0 00002A29 000000000000000000 0 00002A32 000000000000000000 0 00002A3B 000000000000000000 0 00002A44 000000000000000000 0 00002A4D 000000000000000000 0 00002A56 000000000000000000 0 00002A5F 000000000000000000 0 00002A68 000000000000000000 0 00002A71 000000000000000000 0 00002A7A 000000000000000000 0 00002A83 000000000000000000 0 00002A8C 000000000000000000 0 00002A95 000000000000000000 0 00002A9E 000000000000000000 0 00002AA7 000000000000000000 0 00002AB0 000000000000000000 0 00002AB9 000000000000000000 0 00002AC2 000000000000000000 0 00002ACB 000000000000000000 0 00002AD4 000000000000000000 0 00002ADD 000000000000000000 0 00002AE6 000000000000000000 0 00002AEF 000000000000000000 0 00002AF8 000000000000000000 0 00002B01 000000000000000000 0 00002B0A 000000000000000000 0 00002B13 000000000000000000 0 00002B1C 000000000000000000 0 00002B25 000000000000000000 0 00002B2E 000000000000000000 0 00002B37 000000000000000000 0 00002B40 000000000000000000 0 00002B49 000000000000000000 0 00002B52 000000000000000000 0 00002B5B 000000000000000000 0 00002B64 000000000000000000 0 00002B6D 000000000000000000 0 00002B76 000000000000000000 0 00002B7F 000000000000000000 0 00002B88 000000000000000000 0 00002B91 000000000000000000 0 00002B9A 000000000000000000 0 00002BA3 000000000000000000 0 00002BAC 000000000000000000 0 00002BB5 000000000000000000 0 00002BBE 000000000000000000 0 00002BC7 000000000000000000 0 00002BD0 000000000000000000 0 00002BD9 000000000000000000 0 00002BE2 000000000000000000 0 00002BEB 000000000000000000 0 00002BF4 000000000000000000 0 00002BFD 000000000000000000 0 00002C06 000000000000000000 0 00002C0F 000000000000000000 0 00002C18 000000000000000000 0 00002C21 000000000000000000 0 00002C2A 000000000000000000 0 00002C33 000000000000000000 0 00002C3C 000000000000000000 0 00002C45 000000000000000000 0 00002C4E 000000000000000000 0 00002C57 000000000000000000 0 00002C60 000000000000000000 0 00002C69 000000000000000000 0 00002C72 000000000000000000 0 00002C7B 000000000000000000 0 00002C84 000000000000000000 0 00002C8D 000000000000000000 0 00002C96 000000000000000000 0 00002C9F 000000000000000000 0 00002CA8 000000000000000000 0 00002CB1 000000000000000000 0 00002CBA 000000000000000000 0 00002CC3 000000000000000000 0 00002CCC 000000000000000000 0 00002CD5 000000000000000000 0 00002CDE 000000000000000000 0 00002CE7 000000000000000000 0 00002CF0 000000000000000000 0 00002CF9 000000000000000000 0 00002D02 000000000000000000 0 00002D0B 000000000000000000 0 00002D14 000000000000000000 0 00002D1D 000000000000000000 0 00002D26 000000000000000000 0 00002D2F 000000000000000000 0 00002D38 000000000000000000 0 00002D41 000000000000000000 0 00002D4A 000000000000000000 0 00002D53 000000000000000000 0 00002D5C 000000000000000000 0 00002D65 000000000000000000 0 00002D6E 000000000000000000 0 00002D77 000000000000000000 0 00002D80 000000000000000000 0 00002D89 000000000000000000 0 00002D92 000000000000000000 0 00002D9B 000000000000000000 0 00002DA4 000000000000000000 0 00002DAD 000000000000000000 0 00002DB6 000000000000000000 0 00002DBF 000000000000000000 0 00002DC8 000000000000000000 0 00002DD1 000000000000000000 0 00002DDA 000000000000000000 0 00002DE3 000000000000000000 0 00002DEC 000000000000000000 0 00002DF5 000000000000000000 0 00002DFE 000000000000000000 0 00002E07 000000000000000000 0 00002E10 000000000000000000 0 00002E19 000000000000000000 0 00002E22 000000000000000000 0 00002E2B 000000000000000000 0 00002E34 000000000000000000 0 00002E3D 000000000000000000 0 00002E46 000000000000000000 0 00002E4F 000000000000000000 0 00002E58 000000000000000000 0 00002E61 000000000000000000 0 00002E6A 000000000000000000 0 00002E73 000000000000000000 0 00002E7C 000000000000000000 0 00002E85 000000000000000000 0 00002E8E 000000000000000000 0 00002E97 000000000000000000 0 00002EA0 000000000000000000 0 00002EA9 000000000000000000 0 00002EB2 000000000000000000 0 00002EBB 000000000000000000 0 00002EC4 000000000000000000 0 00002ECD 000000000000000000 0 00002ED6 000000000000000000 0 00002EDF 000000000000000000 0 00002EE8 000000000000000000 0 00002EF1 000000000000000000 0 00002EFA 000000000000000000 0 00002F03 000000000000000000 0 00002F0C 000000000000000000 0 00002F15 000000000000000000 0 00002F1E 000000000000000000 0 00002F27 000000000000000000 0 00002F30 000000000000000000 0 00002F39 000000000000000000 0 00002F42 000000000000000000 0 00002F4B 000000000000000000 0 00002F54 000000000000000000 0 00002F5D 000000000000000000 0 00002F66 000000000000000000 0 00002F6F 000000000000000000 0 00002F78 000000000000000000 0 00002F81 000000000000000000 0 00002F8A 000000000000000000 0 00002F93 000000000000000000 0 00002F9C 000000000000000000 0 00002FA5 000000000000000000 0 00002FAE 000000000000000000 0 00002FB7 000000000000000000 0 00002FC0 000000000000000000 0 00002FC9 000000000000000000 0 00002FD2 000000000000000000 0 00002FDB 000000000000000000 0 00002FE4 000000000000000000 0 00002FED 000000000000000000 0 00002FF6 000000000000000000 0 00002FFF 000000000000000000 0 00003008 000000000000000000 0 00003011 000000000000000000 0 0000301A 000000000000000000 0 00003023 000000000000000000 0 0000302C 000000000000000000 0 00003035 000000000000000000 0 0000303E 000000000000000000 0 00003047 000000000000000000 0 00003050 000000000000000000 0 00003059 000000000000000000 0 00003062 000000000000000000 0 0000306B 000000000000000000 0 00003074 000000000000000000 0 0000307D 000000000000000000 0 00003086 000000000000000000 0 0000308F 000000000000000000 0 00003098 000000000000000000 0 000030A1 000000000000000000 0 000030AA 000000000000000000 0 000030B3 000000000000000000 0 000030BC 000000000000000000 0 000030C5 000000000000000000 0 000030CE 000000000000000000 0 000030D7 000000000000000000 0 000030E0 000000000000000000 0 000030E9 000000000000000000 0 000030F2 000000000000000000 0 000030FB 000000000000000000 0 00003104 000000000000000000 0 0000310D 000000000000000000 0 00003116 000000000000000000 0 0000311F 000000000000000000 0 00003128 000000000000000000 0 00003131 000000000000000000 0 0000313A 000000000000000000 0 00003143 000000000000000000 0 0000314C 000000000000000000 0 00003155 000000000000000000 0 0000315E 000000000000000000 0 00003167 000000000000000000 0 00003170 000000000000000000 0 00003179 000000000000000000 0 00003182 000000000000000000 0 0000318B 000000000000000000 0 00003194 000000000000000000 0 0000319D 000000000000000000 0 000031A6 000000000000000000 0 000031AF 000000000000000000 0 000031B8 000000000000000000 0 000031C1 000000000000000000 0 000031CA 000000000000000000 0 000031D3 000000000000000000 0 000031DC 000000000000000000 0 000031E5 000000000000000000 0 000031EE 000000000000000000 0 000031F7 000000000000000000 0 00003200 000000000000000000 0 00003209 000000000000000000 0 00003212 000000000000000000 0 0000321B 000000000000000000 0 00003224 000000000000000000 0 0000322D 000000000000000000 0 00003236 000000000000000000 0 0000323F 000000000000000000 0 00003248 000000000000000000 0 00003251 000000000000000000 0 0000325A 000000000000000000 0 00003263 000000000000000000 0 0000326C 000000000000000000 0 00003275 000000000000000000 0 0000327E 000000000000000000 0 00003287 000000000000000000 0 00003290 000000000000000000 0 00003299 000000000000000000 0 000032A2 000000000000000000 0 000032AB 000000000000000000 0 000032B4 000000000000000000 0 000032BD 000000000000000000 0 000032C6 000000000000000000 0 000032CF 000000000000000000 0 000032D8 000000000000000000 0 000032E1 000000000000000000 0 000032EA 000000000000000000 0 000032F3 000000000000000000 0 000032FC 000000000000000000 0 00003305 000000000000000000 0 0000330E 000000000000000000 0 00003317 000000000000000000 0 00003320 000000000000000000 0 00003329 000000000000000000 0 00003332 000000000000000000 0 0000333B 000000000000000000 0 00003344 000000000000000000 0 0000334D 000000000000000000 0 00003356 000000000000000000 0 0000335F 000000000000000000 0 00003368 000000000000000000 0 00003371 000000000000000000 0 0000337A 000000000000000000 0 00003383 000000000000000000 0 0000338C 000000000000000000 0 00003395 000000000000000000 0 0000339E 000000000000000000 0 000033A7 000000000000000000 0 000033B0 000000000000000000 0 000033B9 000000000000000000 0 000033C2 000000000000000000 0 000033CB 000000000000000000 0 000033D4 000000000000000000 0 000033DD 000000000000000000 0 000033E6 000000000000000000 0 000033EF 000000000000000000 0 000033F8 000000000000000000 0 00003401 000000000000000000 0 0000340A 000000000000000000 0 00003413 000000000000000000 0 0000341C 000000000000000000 0 00003425 000000000000000000 0 0000342E 000000000000000000 0 00003437 000000000000000000 0 00003440 000000000000000000 0 00003449 000000000000000000 0 00003452 000000000000000000 0 0000345B 000000000000000000 0 00003464 000000000000000000 0 0000346D 000000000000000000 0 00003476 000000000000000000 0 0000347F 000000000000000000 0 00003488 000000000000000000 0 00003491 000000000000000000 0 0000349A 000000000000000000 0 000034A3 000000000000000000 0 000034AC 000000000000000000 0 000034B5 000000000000000000 0 000034BE 000000000000000000 0 000034C7 000000000000000000 0 000034D0 000000000000000000 0 000034D9 000000000000000000 0 000034E2 000000000000000000 0 000034EB 000000000000000000 0 000034F4 000000000000000000 0 000034FD 000000000000000000 0 00003506 000000000000000000 0 0000350F 000000000000000000 0 00003518 000000000000000000 0 00003521 000000000000000000 0 0000352A 000000000000000000 0 00003533 000000000000000000 0 0000353C 000000000000000000 0 00003545 000000000000000000 0 0000354E 000000000000000000 0 00003557 000000000000000000 0 00003560 000000000000000000 0 00003569 000000000000000000 0 00003572 000000000000000000 0 0000357B 000000000000000000 0 00003584 000000000000000000 0 0000358D 000000000000000000 0 00003596 000000000000000000 0 0000359F 000000000000000000 0 000035A8 000000000000000000 0 000035B1 000000000000000000 0 000035BA 000000000000000000 0 000035C3 000000000000000000 0 000035CC 000000000000000000 0 000035D5 000000000000000000 0 000035DE 000000000000000000 0 000035E7 000000000000000000 0 000035F0 000000000000000000 0 000035F9 000000000000000000 0 00003602 000000000000000000 0 0000360B 000000000000000000 0 00003614 000000000000000000 0 0000361D 000000000000000000 0 00003626 000000000000000000 0 0000362F 000000000000000000 0 00003638 000000000000000000 0 00003641 000000000000000000 0 0000364A 000000000000000000 0 00003653 000000000000000000 0 0000365C 000000000000000000 0 00003665 000000000000000000 0 0000366E 000000000000000000 0 00003677 000000000000000000 0 00003680 000000000000000000 0 00003689 000000000000000000 0 00003692 000000000000000000 0 0000369B 000000000000000000 0 000036A4 000000000000000000 0 000036AD 000000000000000000 0 000036B6 000000000000000000 0 000036BF 000000000000000000 0 000036C8 000000000000000000 0 000036D1 000000000000000000 0 000036DA 000000000000000000 0 000036E3 000000000000000000 0 000036EC 000000000000000000 0 000036F5 000000000000000000 0 000036FE 000000000000000000 0 00003707 000000000000000000 0 00003710 000000000000000000 0 00003719 000000000000000000 0 00003722 000000000000000000 0 0000372B 000000000000000000 0 00003734 000000000000000000 0 0000373D 000000000000000000 0 00003746 000000000000000000 0 0000374F 000000000000000000 0 00003758 000000000000000000 0 00003761 000000000000000000 0 0000376A 000000000000000000 0 00003773 000000000000000000 0 0000377C 000000000000000000 0 00003785 000000000000000000 0 0000378E 000000000000000000 0 00003797 000000000000000000 0 000037A0 000000000000000000 0 000037A9 000000000000000000 0 000037B2 000000000000000000 0 000037BB 000000000000000000 0 000037C4 000000000000000000 0 000037CD 000000000000000000 0 000037D6 000000000000000000 0 000037DF 000000000000000000 0 000037E8 000000000000000000 0 000037F1 000000000000000000 0 000037FA 000000000000 106 107 Public code_start 108 code_start: 109 110 ; jmp pcmode_init ; PCMODE Init Entry 0 00003800 E9 db 0E9h 0 00003801 [FDC7] dw pcmode_init-PADDING-3 113 ; jmp pcmode_reinit ; PCMODE Re Init Entry 0 00003803 E9 db 0E9h 115 ; dw pcmode_reinit-PADDING-6 0 00003804 [21C9] dw pcmode_init2-PADDING-6 117 118 Public pcmode_dseg, os_version, patch_version 119 0 00003806 0000 pcmode_dseg dw 0 ; 0006h PCMODE Data Segment Pointer 0 00003808 0038 dw PADDING ; 0008h offset of start of code 0 0000380A 7210 os_version dw 1072h ; 000Ah OS version 0 0000380C [00C8] dw patch_area-PADDING ; 000Ch offset of disposable code 0 0000380E [00C8] dw pcmode_init-PADDING ; 000Eh offset of initialisation code 0 00003810 EA db 0EAh ; 0010h JMPF (MUST be para aligned) 0 00003811 C000 dw 4*30h ; 0011h through the Int 30 vec 0 00003813 0000 dw 0 ; 0013h to CALL 5 entry point 0 00003815 00000000000000 db 7 dup (0) ; 0015h make following offsets same as 5.0 0 0000381C 0000 dw 0 ; 001Ch Compressed Data Flag 0 0000381E [00C8] dw code_end-PADDING ; 001Eh PCMODE Code Size in Bytes 0 00003820 [0000] dw data_end ; 0020h PCMODE Data Length in Bytes 0 00003822 0008 patch_version dw DOSINROM+0000h ; 0022h sub-version (was SYSDAT length) 0 00003824 00 db 0 ; 0024h Kanji Support Flag 0 00003825 00 db 0 ; 0025h Reserved 0 00003826 [00C8] dw edit_size-PADDING ; 0026h Pointer Command Line Editor 136 ; control table. 0 00003828 [A001] dw NoYesChars ; 0028h offset in data of pointers to 138 ; default country info. 0 0000382A 000000000000 db 6 dup (0) ; (paragraph alignment) 140 PCM_HEADER ends 141 142 ;**************************************************************************** 143 ; The format of the data is FIXED and should not be modified. 144 ;**************************************************************************** 145 === Switch to base=00C180h -> "PCMODE_DATA" 146 section PCMODE_DATA public align=2 class=DATA 147 148 149 Public codeSeg ; BDOS code segment 150 Public dmd_root ; Root of DOS Memory List 151 Public hmaRoot ; Root of HMA chain 152 Public func52_data ; Start of the FUNC 52 compatible data 153 Public last_drv ; Last Drive 154 Public phys_drv 155 Public dev_root ; Root of Device List 156 Public nul_device ; NUL Device 157 Public ddsc_ptr 158 Public retcode 159 Public user_retcode 160 Public system_retcode 161 Public break_sp 162 Public net_retry 163 Public net_delay 164 Public file_ptr 165 Public clk_device ; Clock Device Pointer 166 Public con_device ; Console Device Pointer 167 Public bcb_root ; Linked List of Buffers 168 Public fcb_ptr 169 Public ldt_ptr 170 Public join_drv 171 Public share_stub 172 Public sector_size 173 Public setverPtr 174 Public dos_version 175 176 Public @hist_flg ; History control flag 177 Public dmd_address ; don't free DMD's with segment under this value 178 Public dmd_owner ; don't free DMD's with owner under this value 179 Public dmd_upper_root ; link to upper memory 180 Public dmd_upper_link 181 Public LocalMachineID ; Normal 0, fixed up by multi-tasker 182 183 Public biosDate ; 6 byte buffer to read/write clock 184 Public minute 185 Public hour 186 Public hundredth 187 Public second 188 Public dayOfMonth 189 Public month 190 Public yearsSince1980 191 Public daysSince1980 192 Public dayOfWeek 193 194 195 org 0 196 0 00000000 00 dos_data db 0 0 00000001 [0038] dw code_start 0 00000003 00 db 0 ; padding 0 00000004 0100 dw 1 201 202 203 ; make end of vladivar instance data public for the multi-tasker 204 db 06h - (offset $ - offset dos_data) dup (0) 0 00000006 [0000] dw endOfInstanceData 206 0 00000008 000000000000 db 0eh - (offset $ - offset dos_data) dup (0) 208 209 Public netbios, name_num, fcb_lru_count 0 0000000E 00 netbios db 0 ; NetBios Name Number 0 0000000F 00 name_num db 0 ; 0 - Undefined Name 0 00000010 0000 fcb_lru_count dw 0 ; fcb LRU counter 213 0 00000012 0000000000000000 db 26h-0ch-(offset $ - offset dos_data) dup (0) ; align func52_data on 26 215 216 ;************************************************************************ 217 ;* * 218 ;* Below is the DOS defined area of the SYSTEM variables * 219 ;* above are variables defined for DR DOS. * 220 ;* * 221 ;************************************************************************ 0 0000001A 0300 net_retry dw 3 ;-000C Network retry count 0 0000001C 0100 net_delay dw 1 ;-000A Network delay count 0 0000001E FFFFFFFF bcb_root dw -1,-1 ;-0008 Current DOS disk buffer 0 00000022 0000 dw 0 ;-0004 Unread CON input 0 00000024 0000 dmd_root dw 0 ;-0002 Root of DOS Memory List (Segment) 227 func52_data label byte 228 ddsc_ptr label dword ; 0000 DWORD ptr to DDSC 0 00000026 FFFFFFFF dw -1,-1 230 file_ptr label dword ; 0004 DWORD ptr file table 0 0000002A [CC00]0000 dw msdos_file_tbl,0 232 clk_device label dword ; 0008 DWORD ptr Clock Device Header 0 0000002E FFFFFFFF dw -1,-1 ; Initialize to an Invalid Address 234 con_device label dword ; 000C DWORD ptr Console Device Header 0 00000032 FFFFFFFF dw -1,-1 ; Initialize to an Invalid Address 0 00000036 8000 sector_size dw 128 ; 0010 WORD Buffer Size (Max Sector Size) 0 00000038 [6D00]0000 buf_ptr dw buf_info,0 ; 0012 DWORD ptr to Disk Buffer Info 0 0000003C 00000000 ldt_ptr dw 0,0 ; 0016 DWORD ptr Path Structures 0 00000040 [F001]0000 fcb_ptr dw dummy_fcbs,0 ; 001A DWORD ptr FCB Control Structures 0 00000044 0000 dw 0 ; 001E WORD UNKNOWN 0 00000046 00 phys_drv db 0 ; 0020 BYTE Number of Physical Drives 0 00000047 00 last_drv db 0 ; 0021 BYTE Last Drive 243 dev_root label dword ; 0022 DWORD ptr Device Driver List 0 00000048 FFFFFFFF nul_device dw -1,-1 ; Next Device Pointer 0 0000004C 0480 dw DA_CHARDEV+DA_ISNUL ; 0026 NUL Device Attributes 0 0000004E [ED00] dw nul_strat ; 0028 NUL Device Strategy routine 0 00000050 [0001] dw nul_int ; 002A NUL Device Interrupt routine 0 00000052 4E554C2020202020 db 'NUL ' ; 002C NUL Device Name 0 0000005A 00 join_drv db 0 ; 0034 BYTE Number of JOIN'd drives 0 0000005B 0000 dw 0 ; 0035 DOS 4 pointer to special names (always zero in DOS 5) 0 0000005D 00000000 setverPtr dw 0,0 ; 0037 setver list 0 00000061 0000 dw 0 ; 003B unknown 0 00000063 0000 dw 0 ; 003D psp of last umb exec 0 00000065 0100 dw 1 ; 003F number of buffers 0 00000067 0100 dw 1 ; 0041 size of pre-read buffer 256 public bootDrv 0 00000069 00 bootDrv db 0 ; 0043 drive we booted from 0 0000006A 00 db 0 ; 0044 cpu type (1 if >=386) 0 0000006B 0000 dw 0 ; 0045 Extended memory 0 0000006D 00000000 buf_info dd 0 ; 0047 disk buffer chain 0 00000071 0000 dw 0 ; 004B 0 (DOS 4 = # hashing chains) 0 00000073 00000000 dd 0 ; 004D pre-read buffer 0 00000077 0000 dw 0 ; 0051 # of sectors 0 00000079 00 db 0 ; 0053 00=conv 01=HMA 0 0000007A 0000 dw 0 ; 0054 deblock buf in conv 0 0000007C 0000 deblock_seg dw 0 ; 0056 (offset always zero) 0 0000007E 000000 db 3 dup (0) ; 0058 unknown 0 00000081 0000 dw 0 ; 005B unknown 0 00000083 00FF00 db 0, 0FFh, 0 ; 005D unknown 0 00000086 00 db 0 ; 0060 unknown 0 00000087 0000 dw 0 ; 0061 unknown 0 00000089 00 dmd_upper_link db 0 ; 0063 upper memory link flag 0 0000008A 0000 dw 0 ; 0064 unknown 0 0000008C FFFF dmd_upper_root dw 0FFFFh ; 0066 dmd_upper_root 0 0000008E 0000 dw 0 ; 0068 para of last mem search 276 0 00000090 [0201]0000 dw invalid_stub,0 ; 006A DWORD ptr to 15 0 00000094 [0001]0000 dw nul_int,0 ; 006E SHARE STUB routines 0 00000098 [0001]0000 dw nul_int,0 ; 0072 0 0000009C [0001]0000 dw nul_int,0 ; 0076 0 000000A0 [0001]0000 dw nul_int,0 ; 007A 0 000000A4 [0001]0000 dw nul_int,0 ; 007E 0 000000A8 [0001]0000 dw nul_int,0 ; 0082 0 000000AC [0001]0000 dw nul_int,0 ; 0086 0 000000B0 [0001]0000 dw nul_int,0 ; 008A 0 000000B4 [0001]0000 dw nul_int,0 ; 008E 0 000000B8 [0201]0000 dw invalid_stub,0 ; 0092 0 000000BC [0001]0000 dw nul_int,0 ; 0096 0 000000C0 [0001]0000 dw nul_int,0 ; 009A 0 000000C4 [0001]0000 dw nul_int,0 ; 009E 0 000000C8 [0001]0000 dw nul_int,0 ; 00A2 292 0 000000CC FFFF msdos_file_tbl dw -1 ; 00A6 1st HDB entries 0 000000CE FFFF dw -1 ; Pointer to next Entry (None) 0 000000D0 0300 dw 3 ; Number of Entries 296 0 000000D2 000000000000000000 db 3*DHNDL_LEN dup (0) ; Reserve 5 Internal Handles 0 000000DB 000000000000000000 0 000000E4 000000000000000000 0 000000ED 000000000000000000 0 000000F6 000000000000000000 0 000000FF 000000000000000000 0 00000108 000000000000000000 0 00000111 000000000000000000 0 0000011A 000000000000000000 0 00000123 000000000000000000 0 0000012C 000000000000000000 0 00000135 000000000000000000 0 0000013E 000000000000000000 0 00000147 000000000000000000 0 00000150 000000000000000000 0 00000159 000000000000000000 0 00000162 000000000000000000 0 0000016B 000000000000000000 0 00000174 000000000000000000 0 0000017D 000000000000000000 0 00000186 000000000000000000 0 0000018F 000000000000000000 0 00000198 000000000000000000 0 000001A1 000000000000000000 0 000001AA 000000000000000000 298 0 000001B3 000000000000000000 db 1fbh - (offset $ - offset dos_data) dup (0) 0 000001BC 000000000000000000 0 000001C5 000000000000000000 0 000001CE 000000000000000000 0 000001D7 000000000000000000 0 000001E0 000000000000000000 0 000001E9 000000000000000000 0 000001F2 000000000000000000 300 301 Public savbuf 302 ;savbuf rb 128 ; cmdline editing temp buffer 0 000001FB 000000000000000000 savbuf db CMDLINE_LEN dup (0) ; cmdline editing temp buffer 0 00000204 000000000000000000 0 0000020D 000000000000000000 0 00000216 000000000000000000 0 0000021F 000000000000000000 0 00000228 000000000000000000 0 00000231 000000000000000000 0 0000023A 000000000000000000 0 00000243 000000000000000000 0 0000024C 000000000000000000 0 00000255 000000000000000000 0 0000025E 000000000000000000 0 00000267 000000000000000000 0 00000270 000000000000000000 0 00000279 0000 304 Public fdos_buf 0 0000027B 0200 fdos_buf db 2,0 ; initialise buffer to empty 306 ; rb 128+1 ; room for 128 byte readline + LF 0 0000027D 000000000000000000 db CMDLINE_LEN+1 dup (0) ; room for 128 byte readline + LF 0 00000286 000000000000000000 0 0000028F 000000000000000000 0 00000298 000000000000000000 0 000002A1 000000000000000000 0 000002AA 000000000000000000 0 000002B3 000000000000000000 0 000002BC 000000000000000000 0 000002C5 000000000000000000 0 000002CE 000000000000000000 0 000002D7 000000000000000000 0 000002E0 000000000000000000 0 000002E9 000000000000000000 0 000002F2 000000000000000000 0 000002FB 000000 308 309 db 2feh - (offset $ - offset dos_data) dup (0) 310 ; this byte is used for ^P support 311 Public cio_state 0 000002FE 00 cio_state db 0 ; 0 = no printer echo, ~0 echo 313 Public verify_flag 0 000002FF 00 verify_flag db 0 ; ~0, write with verify 315 316 db 300h - (offset $ - offset dos_data) dup (0) 317 ; this byte is used for TAB's 318 Public column 0 00000300 00 column db 0 ; Current Cursor Column 320 Public switch_char 0 00000301 2F switch_char db '/' 322 Public mem_strategy 0 00000302 00 mem_strategy db 0 ; memory allocation strategy 324 Public sharing_flag 0 00000303 00 sharing_flag db 0 ; 00 = sharing module not loaded 326 ; 01 = sharing module loaded, but 327 ; open/close for block devices 328 ; disabled 329 ; FF = sharing module loaded, 330 ; open/close for block devices 331 ; enabled (not implemented) 332 Public net_set_count 0 00000304 01 net_set_count db 1 ; count the name below was set 334 Public net_name 0 00000305 202020202020202020 net_name db ' ' ; 15 Character Network Name 0 0000030E 202020202020 0 00000314 00 db 00 ; Terminating 0 byte 337 338 ; These tables point to routines to be patched by MSNET 0 00000315 [2901] dw criticalSectionEnable 0 00000317 [2901] dw criticalSectionEnable 0 00000319 [2901] dw criticalSectionEnable 0 0000031B [2901] dw criticalSectionEnable 0 0000031D 0000 dw 0 ; terminating null 344 0 0000031F 00 db 0 ; padding 346 347 ; 348 ; Variables contained the the "STATE_DATA" segment contain 349 ; information about the STATE of the current DOS Process. These 350 ; variables must be preserved regardless of the state of the INDOS 351 ; flag. 352 ; 353 ; All variables that appear in "STATE_DATA" **MUST** be declared 354 ; in this file as the offsets from the INTERNAL_DATA variable are 355 ; critical to the DOS applications that modify this data area. 356 ; 357 ; 358 Public error_flag, indos_flag 359 Public error_locus, error_code 360 Public error_action, error_class 361 Public error_dev, error_drive 362 Public dma_offset, dma_segment 363 Public current_psp, current_dsk 364 Public break_flag 365 366 Public internal_data 367 368 internal_data label word ; <-- Address returned by INT21/5D06 0 00000320 00 error_flag db 0 ; INDOS - 01 - Error Mode Flag 0 00000321 00 indos_flag db 0 ; INDOS + 00 - Indos Flag 0 00000322 00 error_drive db 0 ; INDOS + 01 - Drive on write protect error 0 00000323 00 error_locus db 0 ; INDOS + 02 - Error Locus 0 00000324 0000 error_code dw 0 ; INDOS + 03 - DOS format error Code 0 00000326 00 error_action db 0 ; INDOS + 05 - Error Action Code 0 00000327 00 error_class db 0 ; INDOS + 06 - Error Class 0 00000328 00000000 error_dev dd 0 ; INDOS + 07 - Failing Device Address 0 0000032C 0000 dma_offset dw 0 ; INDOS + 0B - DMA Offset 0 0000032E 0000 dma_segment dw 0 ; INDOS + 0D - DMA Segment 0 00000330 0000 current_psp dw 0 ; INDOS + 0F - Current PSP 0 00000332 0000 break_sp dw 0 ; INDOS + 11 - used in int 23 381 retcode label word 0 00000334 00 user_retcode db 0 ; INDOS + 13 - return code from process 0 00000335 00 system_retcode db 0 ; INDOS + 14 - reason for process terminate 0 00000336 00 current_dsk db 0 ; INDOS + 15 - Current Drive 0 00000337 00 break_flag db 0 ; INDOS + 16 - Break Flag 0 00000338 0000 dw 0 ; INDOS + 17 - unknown 387 388 Public swap_always 389 swap_always label dword 390 391 Public int21AX 0 0000033A 0000 int21AX dw 0 ; INDOS + 19 - AX from last Int 21 393 394 Public owning_psp, machine_id 0 0000033C 0000 owning_psp dw 0 ; INDOS + 1B - owning psp 0 0000033E 0000 machine_id dw 0 ; INDOS + 1D - remote machine ID 397 398 399 public load_psp, load_image, load_top, load_max, load_handle 400 0 00000340 0000 load_psp dw 0 ; Paragraph of the new PSP. 0 00000342 0000 load_image dw 0 ; Paragraph of the Load Image. 0 00000344 0000 load_top dw 0 ; Last paragraph of Allocated Memory 0 00000346 0000 load_max dw 0 ; ditto, but not messed with 0 00000348 0000 load_handle dw 0 ; Handle allocated to load file on OPEN 406 407 Public locus, valid_flg, retry_off, retry_sp 0 0000034A 00 locus db 0 ; Public Error Locus Value 0 0000034B 00 valid_flg db 0 ; Valid Options for Critical Error 0 0000034C 0000 retry_off dw 0 ; IP for Error Retry 0 0000034E 0000 retry_sp dw 0 ; SP for Error Retry 412 413 414 415 ; Some important data structures.... 416 db 0350h - ($ - offset dos_data) dup (0) ; DOS 5 0 00000350 00 dayOfMonth db 0 0 00000351 00 month db 0 0 00000352 0000 yearsSince1980 dw 0 0 00000354 FFFF daysSince1980 dw 0FFFFh ; force rebuild on first clock read 0 00000356 00 dayOfWeek db 0 422 423 public internal_flag 0 00000357 00 internal_flag db 0 425 426 Public int28_flag 0 00000358 00 int28_flag db FALSE 428 429 430 public ioctlRH 431 0 00000359 000000000000000000 ioctlRH db 23 dup (0) ; up to 23 bytes possible 0 00000362 000000000000000000 0 0000036B 0000000000 433 434 public load_env, load_envsize, exe_loadhigh 0 00000370 0000 load_env dw 0 ; Paragraph of the new environment 0 00000372 0000 load_envsize dw 0 ; Size of new environment 0 00000374 00 exe_loadhigh db 0 ; load high flag 438 439 440 Public fcb_pb, fcb_path, fcb_path2 441 442 ; These variables are used during FCB processing - we build another parameter 443 ; block outside the MXDisk which makes handle calls to the FDOS 444 0 00000375 000000000000000000 fcb_pb dw 7 dup (0) 0 0000037E 0000000000 0 00000383 000000000000000000 fcb_path db 15 dup (0) 0 0000038C 000000000000 0 00000392 000000000000000000 fcb_path2 db 15 dup (0) 0 0000039B 000000000000 448 449 public char_count 0 000003A1 00 char_count db 0 451 452 PCMODE_DATA ends 453 454 ;**************************************************************************** 455 ; The format of the data is FIXED and should not be modified. 456 ;**************************************************************************** 457 458 ; WARNING - if anyone adds/deletes PCMODE_DATA they MUST adjust these 459 ; values so the following data will origin correctly === Switch to base=00C180h -> "FIXED_DOS_DATA" 460 section FIXED_DOS_DATA public align=2 class=DATA 461 462 FIXED_DATA_START equ 3B0h 463 public MUSTBE03B0 464 MUSTBE03B0: 465 0 000003B0 00 org 03b6h - FIXED_DATA_START ; DOS 5 0 000003B6 0000 biosDate dw 0 ; days since 1980 0 000003B8 00 minute db 0 0 000003B9 00 hour db 0 0 000003BA 00 hundredth db 0 0 000003BB 00 second db 0 0 000003BC 0000 db 2 dup (0) ; padding 473 474 Public reloc_buf, load_file, RELOC_CNT 475 RELOC_CNT equ 80h/16 ; buffer 128 bytes here 476 477 ; function 4B uses these data area's as workspace during an EXEC 478 479 Public pri_pathname 480 reloc_buf label byte ; shared with primary pathname 0 000003BE 000000000000000000 pri_pathname db 80h dup (0) 0 000003C7 000000000000000000 0 000003D0 000000000000000000 0 000003D9 000000000000000000 0 000003E2 000000000000000000 0 000003EB 000000000000000000 0 000003F4 000000000000000000 0 000003FD 000000000000000000 0 00000406 000000000000000000 0 0000040F 000000000000000000 0 00000418 000000000000000000 0 00000421 000000000000000000 0 0000042A 000000000000000000 0 00000433 000000000000000000 0 0000043C 0000 482 Public sec_pathname 483 load_file label byte 0 0000043E 000000000000000000 sec_pathname db 80h dup (0) 0 00000447 000000000000000000 0 00000450 000000000000000000 0 00000459 000000000000000000 0 00000462 000000000000000000 0 0000046B 000000000000000000 0 00000474 000000000000000000 0 0000047D 000000000000000000 0 00000486 000000000000000000 0 0000048F 000000000000000000 0 00000498 000000000000000000 0 000004A1 000000000000000000 0 000004AA 000000000000000000 0 000004B3 000000000000000000 0 000004BC 0000 485 Public srch_buf 0 000004BE 000000000000000000 srch_buf db 21+32 dup (0) ; 21 byte srch state, 32 byte dir entry 0 000004C7 000000000000000000 0 000004D0 000000000000000000 0 000004D9 000000000000000000 0 000004E2 000000000000000000 0 000004EB 0000000000000000 487 Public temp_ldt 0 000004F3 000000000000000000 temp_ldt db LDT_LEN dup (0) 0 000004FC 000000000000000000 0 00000505 000000000000000000 0 0000050E 000000000000000000 0 00000517 000000000000000000 0 00000520 000000000000000000 0 00000529 000000000000000000 0 00000532 000000000000000000 0 0000053B 000000000000000000 0 00000544 00000000000000 489 Public name_buf 0 0000054B 000000000000000000 name_buf db 32 dup (0) ; space enough for 1 dir entry 0 00000554 000000000000000000 0 0000055D 000000000000000000 0 00000566 0000000000 491 0 0000056B 00 magic_byte db 0 0 0000056C 00 db 0 ; padding 494 Public file_attrib 0 0000056D 0000 file_attrib dw 0 0 0000056F 000000 db 3 dup (0) ; padding 497 Public remote_call 0 00000572 0000 remote_call dw 0 499 500 0 00000574 00 org 057Ch - FIXED_DATA_START 502 Public exit_type ; used by break and critical error 0 0000057C 00 exit_type db 0 ; handlers during termination 0 0000057D 00 db 0 ; padding 505 Public term_psp 0 0000057E 0000 term_psp dw 0 507 508 Public int24_esbp 0 00000580 00000000 int24_esbp dw 2 dup (0) 510 Public int21regs_ptr, int21regs_off, int21regs_seg 511 int21regs_ptr label word 0 00000584 0000 int21regs_off dw 0 0 00000586 0000 int21regs_seg dw 0 514 public critical_sp 0 00000588 0000 critical_sp dw 0 ; critical error internal stack 516 Public current_ddsc 0 0000058A 00000000 current_ddsc dw 2 dup (0) 518 0 0000058E 00 org 059ah - FIXED_DATA_START 520 Public current_device 0 0000059A 00000000 current_device dw 2 dup (0) 522 Public current_dhndl 0 0000059E 00000000 current_dhndl dw 2 dup (0) 524 Public current_ldt 0 000005A2 00000000 current_ldt dw 2 dup (0) 0 000005A6 00000000 dw 2 dup (0) ; pointer to callers FCB 527 Public current_ifn 0 000005AA 0000 current_ifn dw 0 529 0 000005AC 00 org 05b2h - FIXED_DATA_START 0 000005B2 [0E00] dw offset pri_pathname 0 000005B4 [8E00] dw offset sec_pathname 0 000005B6 [0E00] dw offset pri_pathname 534 0 000005B8 00 org 05ceh - FIXED_DATA_START 536 Public current_filepos 0 000005CE 0000000000000000 current_filepos dw 4 dup (0) 538 0 000005D6 00 org 05f0h - FIXED_DATA_START 540 Public prev_int21regs_ptr, prev_int21regs_off, prev_int21regs_seg 541 prev_int21regs_ptr label word 0 000005F0 0000 prev_int21regs_off dw 0 0 000005F2 0000 prev_int21regs_seg dw 0 544 0 000005F4 00 org 0620h - FIXED_DATA_START 546 547 Public indos_stack, error_stack, normal_stack 548 549 Public fcb_search_buf ; during FCB search 1st/next use bottom 550 fcb_search_buf label byte ; of error stack as scratch buffer 551 ; db 43 dup (0) ; - only used during int 21 call 552 0 00000620 000000000000000000 dw STACK_SIZE dup (0) ; Error Processing Stack 0 00000629 000000000000000000 0 00000632 000000000000000000 0 0000063B 000000000000000000 0 00000644 000000000000000000 0 0000064D 000000000000000000 0 00000656 000000000000000000 0 0000065F 000000000000000000 0 00000668 000000000000000000 0 00000671 000000000000000000 0 0000067A 000000000000000000 0 00000683 000000000000000000 0 0000068C 000000000000000000 0 00000695 000000000000000000 0 0000069E 000000000000000000 0 000006A7 000000000000000000 0 000006B0 000000000000000000 0 000006B9 000000000000000000 0 000006C2 000000000000000000 0 000006CB 000000000000000000 0 000006D4 000000000000000000 0 000006DD 000000000000000000 0 000006E6 000000000000000000 0 000006EF 000000000000000000 0 000006F8 000000000000000000 0 00000701 000000000000000000 0 0000070A 000000000000000000 0 00000713 000000000000000000 0 0000071C 000000000000000000 0 00000725 000000000000000000 0 0000072E 000000000000000000 0 00000737 000000000000000000 0 00000740 000000000000000000 0 00000749 000000000000000000 0 00000752 000000000000000000 0 0000075B 000000000000000000 0 00000764 000000000000000000 0 0000076D 000000000000000000 0 00000776 000000000000000000 0 0000077F 000000000000000000 0 00000788 000000000000000000 0 00000791 000000000000000000 0 0000079A 000000000000 554 error_stack label word 555 0 000007A0 000000000000000000 dw STACK_SIZE dup (0) ; Normal Function Stack Area 0 000007A9 000000000000000000 0 000007B2 000000000000000000 0 000007BB 000000000000000000 0 000007C4 000000000000000000 0 000007CD 000000000000000000 0 000007D6 000000000000000000 0 000007DF 000000000000000000 0 000007E8 000000000000000000 0 000007F1 000000000000000000 0 000007FA 000000000000000000 0 00000803 000000000000000000 0 0000080C 000000000000000000 0 00000815 000000000000000000 0 0000081E 000000000000000000 0 00000827 000000000000000000 0 00000830 000000000000000000 0 00000839 000000000000000000 0 00000842 000000000000000000 0 0000084B 000000000000000000 0 00000854 000000000000000000 0 0000085D 000000000000000000 0 00000866 000000000000000000 0 0000086F 000000000000000000 0 00000878 000000000000000000 0 00000881 000000000000000000 0 0000088A 000000000000000000 0 00000893 000000000000000000 0 0000089C 000000000000000000 0 000008A5 000000000000000000 0 000008AE 000000000000000000 0 000008B7 000000000000000000 0 000008C0 000000000000000000 0 000008C9 000000000000000000 0 000008D2 000000000000000000 0 000008DB 000000000000000000 0 000008E4 000000000000000000 0 000008ED 000000000000000000 0 000008F6 000000000000000000 0 000008FF 000000000000000000 0 00000908 000000000000000000 0 00000911 000000000000000000 0 0000091A 000000000000 557 normal_stack label word 558 0 00000920 000000000000000000 dw STACK_SIZE dup (0) ; Indos Function Stack 0 00000929 000000000000000000 0 00000932 000000000000000000 0 0000093B 000000000000000000 0 00000944 000000000000000000 0 0000094D 000000000000000000 0 00000956 000000000000000000 0 0000095F 000000000000000000 0 00000968 000000000000000000 0 00000971 000000000000000000 0 0000097A 000000000000000000 0 00000983 000000000000000000 0 0000098C 000000000000000000 0 00000995 000000000000000000 0 0000099E 000000000000000000 0 000009A7 000000000000000000 0 000009B0 000000000000000000 0 000009B9 000000000000000000 0 000009C2 000000000000000000 0 000009CB 000000000000000000 0 000009D4 000000000000000000 0 000009DD 000000000000000000 0 000009E6 000000000000000000 0 000009EF 000000000000000000 0 000009F8 000000000000000000 0 00000A01 000000000000000000 0 00000A0A 000000000000000000 0 00000A13 000000000000000000 0 00000A1C 000000000000000000 0 00000A25 000000000000000000 0 00000A2E 000000000000000000 0 00000A37 000000000000000000 0 00000A40 000000000000000000 0 00000A49 000000000000000000 0 00000A52 000000000000000000 0 00000A5B 000000000000000000 0 00000A64 000000000000000000 0 00000A6D 000000000000000000 0 00000A76 000000000000000000 0 00000A7F 000000000000000000 0 00000A88 000000000000000000 0 00000A91 000000000000000000 0 00000A9A 000000000000 560 indos_stack label word 561 0 00000AA0 00 lookahead_flag db 0 563 564 Public rwmode, err_drv, ioexerr 0 00000AA1 00 err_drv db 0 0 00000AA2 00 rwmode db 0 0 00000AA3 00 ioexerr db 0 568 public int2f_cmd, int2f_stack, file_mode 0 00000AA4 0000 int2f_cmd dw 0 0 00000AA6 0000 int2f_stack dw 0 0 00000AA8 0000 file_mode dw 0 572 Public cle_state 0 00000AAA 0000 cle_state dw 0 574 Public swap_indos 575 swap_indos label word 576 0 00000AAC 00 org 0AADh - FIXED_DATA_START 578 0 00000AAD 8000 Ucasetbl dw 128 ; Table Size 0 00000AAF 809A45418E418F80 db 080h, 09ah, 'E', 'A', 08eh, 'A', 08fh, 080h 0 00000AB7 4545454949498E8F db 'E', 'E', 'E', 'I', 'I', 'I', 08eh, 08fh 0 00000ABF 9092924F994F5555 db 090h, 092h, 092h, 'O', 099h, 'O', 'U', 'U' 0 00000AC7 59999A9B9C9D9E9F db 'Y', 099h, 09ah, 09bh, 09ch, 09dh, 09eh, 09fh 0 00000ACF 41494F55A5A5A6A7 db 'A', 'I', 'O', 'U', 0a5h, 0a5h, 0a6h, 0a7h 0 00000AD7 A8A9AAABACADAEAF db 0a8h, 0a9h, 0aah, 0abh, 0ach, 0adh, 0aeh, 0afh 0 00000ADF B0B1B2B3B4B5B6B7 db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 0b5h, 0b6h, 0b7h 0 00000AE7 B8B9BABBBCBDBEBF db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh, 0beh, 0bfh 0 00000AEF C0C1C2C3C4C5C6C7 db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 0c6h, 0c7h 0 00000AF7 C8C9CACBCCCDCECF db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 0cfh 0 00000AFF D0D1D2D3D4D5D6D7 db 0d0h, 0d1h, 0d2h, 0d3h, 0d4h, 0d5h, 0d6h, 0d7h 0 00000B07 D8D9DADBDCDDDEDF db 0d8h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 0deh, 0dfh 0 00000B0F E0E1E2E3E4E5E6E7 db 0e0h, 0e1h, 0e2h, 0e3h, 0e4h, 0e5h, 0e6h, 0e7h 0 00000B17 E8E9EAEBECEDEEEF db 0e8h, 0e9h, 0eah, 0ebh, 0ech, 0edh, 0eeh, 0efh 0 00000B1F F0F1F2F3F4F5F6F7 db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h 0 00000B27 F8F9FAFBFCFDFEFF db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh 596 info2_len equ (offset $ - offset Ucasetbl) 597 598 599 org 0B2Fh - FIXED_DATA_START 600 ; Filename upper case table 0 00000B2F 8000 FileUcasetbl dw 128 ; Table Size 602 standard_table label byte 0 00000B31 809A45418E418F80 db 080h, 09ah, 'E', 'A', 08eh, 'A', 08fh, 080h 0 00000B39 4545454949498E8F db 'E', 'E', 'E', 'I', 'I', 'I', 08eh, 08fh 0 00000B41 9092924F994F5555 db 090h, 092h, 092h, 'O', 099h, 'O', 'U', 'U' 0 00000B49 59999A9B9C9D9E9F db 'Y', 099h, 09ah, 09bh, 09ch, 09dh, 09eh, 09fh 0 00000B51 41494F55A5A5A6A7 db 'A', 'I', 'O', 'U', 0a5h, 0a5h, 0a6h, 0a7h 0 00000B59 A8A9AAABACADAEAF db 0a8h, 0a9h, 0aah, 0abh, 0ach, 0adh, 0aeh, 0afh 0 00000B61 B0B1B2B3B4B5B6B7 db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 0b5h, 0b6h, 0b7h 0 00000B69 B8B9BABBBCBDBEBF db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh, 0beh, 0bfh 0 00000B71 C0C1C2C3C4C5C6C7 db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 0c6h, 0c7h 0 00000B79 C8C9CACBCCCDCECF db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 0cfh 0 00000B81 D0D1D2D3D4D5D6D7 db 0d0h, 0d1h, 0d2h, 0d3h, 0d4h, 0d5h, 0d6h, 0d7h 0 00000B89 D8D9DADBDCDDDEDF db 0d8h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 0deh, 0dfh 0 00000B91 E0E1E2E3E4E5E6E7 db 0e0h, 0e1h, 0e2h, 0e3h, 0e4h, 0e5h, 0e6h, 0e7h 0 00000B99 E8E9EAEBECEDEEEF db 0e8h, 0e9h, 0eah, 0ebh, 0ech, 0edh, 0eeh, 0efh 0 00000BA1 F0F1F2F3F4F5F6F7 db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h 0 00000BA9 F8F9FAFBFCFDFEFF db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh 619 620 info4_len equ (offset $ - offset FileUcasetbl) 621 622 org 0BB1h - FIXED_DATA_START 623 624 FileCharstbl: 0 00000BB1 1600 dw 22 ; Table Size 0 00000BB3 0100FF000020020E db 001h, 000h, 0ffh, 000h, 000h, 020h, 002h, 00eh 0 00000BBB 2E222F5C5B5D3A7C db 02eh, 022h, 02fh, 05ch, 05bh, 05dh, 03ah, 07ch 0 00000BC3 3C3E2B3D3B2C db 03ch, 03eh, 02bh, 03dh, 03bh, 02ch 629 info5_len equ (offset $ - offset FileCharstbl) 630 0 00000BC9 00 org 0BE1h - FIXED_DATA_START 632 633 Collatingtbl: 0 00000BE1 0001 dw 256 ; Table Size 0 00000BE3 0001020304050607 db 000h, 001h, 002h, 003h, 004h, 005h, 006h, 007h 0 00000BEB 08090A0B0C0D0E0F db 008h, 009h, 00ah, 00bh, 00ch, 00dh, 00eh, 00fh 0 00000BF3 1011121314151617 db 010h, 011h, 012h, 013h, 014h, 015h, 016h, 017h 0 00000BFB 18191A1B1C1D1E1F db 018h, 019h, 01ah, 01bh, 01ch, 01dh, 01eh, 01fh 0 00000C03 2021222324252627 db 020h, 021h, 022h, 023h, 024h, 025h, 026h, 027h 0 00000C0B 28292A2B2C2D2E2F db 028h, 029h, 02ah, 02bh, 02ch, 02dh, 02eh, 02fh 0 00000C13 3031323334353637 db 030h, 031h, 032h, 033h, 034h, 035h, 036h, 037h 0 00000C1B 38393A3B3C3D3E3F db 038h, 039h, 03ah, 03bh, 03ch, 03dh, 03eh, 03fh 0 00000C23 4041424344454647 db 040h, 041h, 042h, 043h, 044h, 045h, 046h, 047h 0 00000C2B 48494A4B4C4D4E4F db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh 0 00000C33 5051525354555657 db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h 0 00000C3B 58595A5B5C5D5E5F db 058h, 059h, 05ah, 05bh, 05ch, 05dh, 05eh, 05fh 0 00000C43 6041424344454647 db 060h, 041h, 042h, 043h, 044h, 045h, 046h, 047h 0 00000C4B 48494A4B4C4D4E4F db 048h, 049h, 04ah, 04bh, 04ch, 04dh, 04eh, 04fh 0 00000C53 5051525354555657 db 050h, 051h, 052h, 053h, 054h, 055h, 056h, 057h 0 00000C5B 58595A7B7C7D7E7F db 058h, 059h, 05ah, 07bh, 07ch, 07dh, 07eh, 07fh 0 00000C63 4355454141414143 db 043h, 055h, 045h, 041h, 041h, 041h, 041h, 043h 0 00000C6B 4545454949494141 db 045h, 045h, 045h, 049h, 049h, 049h, 041h, 041h 0 00000C73 4541414F4F4F5555 db 045h, 041h, 041h, 04fh, 04fh, 04fh, 055h, 055h 0 00000C7B 594F552424242424 db 059h, 04fh, 055h, 024h, 024h, 024h, 024h, 024h 0 00000C83 41494F554E4EA6A7 db 041h, 049h, 04fh, 055h, 04eh, 04eh, 0a6h, 0a7h 0 00000C8B 3FA9AAABAC212222 db 03fh, 0a9h, 0aah, 0abh, 0ach, 021h, 022h, 022h 0 00000C93 B0B1B2B3B4B5B6B7 db 0b0h, 0b1h, 0b2h, 0b3h, 0b4h, 0b5h, 0b6h, 0b7h 0 00000C9B B8B9BABBBCBDBEBF db 0b8h, 0b9h, 0bah, 0bbh, 0bch, 0bdh, 0beh, 0bfh 0 00000CA3 C0C1C2C3C4C5C6C7 db 0c0h, 0c1h, 0c2h, 0c3h, 0c4h, 0c5h, 0c6h, 0c7h 0 00000CAB C8C9CACBCCCDCECF db 0c8h, 0c9h, 0cah, 0cbh, 0cch, 0cdh, 0ceh, 0cfh 0 00000CB3 D0D1D2D3D4D5D6D7 db 0d0h, 0d1h, 0d2h, 0d3h, 0d4h, 0d5h, 0d6h, 0d7h 0 00000CBB D8D9DADBDCDDDEDF db 0d8h, 0d9h, 0dah, 0dbh, 0dch, 0ddh, 0deh, 0dfh 0 00000CC3 E053E2E3E4E5E6E7 db 0e0h, 053h, 0e2h, 0e3h, 0e4h, 0e5h, 0e6h, 0e7h 0 00000CCB E8E9EAEBECEDEEEF db 0e8h, 0e9h, 0eah, 0ebh, 0ech, 0edh, 0eeh, 0efh 0 00000CD3 F0F1F2F3F4F5F6F7 db 0f0h, 0f1h, 0f2h, 0f3h, 0f4h, 0f5h, 0f6h, 0f7h 0 00000CDB F8F9FAFBFCFDFEFF db 0f8h, 0f9h, 0fah, 0fbh, 0fch, 0fdh, 0feh, 0ffh 667 info6_len equ (offset $ - offset Collatingtbl) 668 669 org 0CE3h - FIXED_DATA_START 670 671 DBCS_tbl: 0 00000CE3 0000 dw 0 ; Table Size 0 00000CE5 0000000000000000 db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h 0 00000CED 0000000000000000 db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h 675 info7_len equ (offset $ - offset DBCS_tbl) 676 677 ; org 0d12h - FIXED_DATA_START 0 00000CF5 00 org 0d10h - FIXED_DATA_START 679 0 00000D10 0701 true_version dw 107h ; true DOS version 0 00000D12 0600 dos_version dw 6 ; our DOS version number 682 683 ; Don't know what these are for..... 0 00000D14 C8A6 db 0c8h,0a6h 0 00000D16 C8A5 db 0c8h,0a5h 0 00000D18 C8A5 db 0c8h,0a5h 0 00000D1A C8A5 db 0c8h,0a5h 688 689 ; Now we have a list of days in each month 690 Public days_in_month 691 0 00000D1C 1F1C1F1E1F1E days_in_month db 31,28,31,30,31,30 ; Jan, Feb, Mar, Apr, May, Jun 0 00000D22 1F1F1E1F1E1F db 31,31,30,31,30,31 ; Jul, Aug, Sep, Oct, Nov, Dec 694 0 00000D28 00 org 0d90h - FIXED_DATA_START 696 697 Public last_key_ext 698 0 00000D90 00 last_key_ext db 0 ; flag set if last key zero 700 0 00000D91 00 org 0e5bh - FIXED_DATA_START 702 703 ; 704 ; Extended Error/Class/Action/Locus table. Used in conjuction with 705 ; Int2F/1222 to setup extended error information 0 00000E5B 130B0702 db 13h,0Bh,07h,02h 0 00000E5F 14040501 db 14h,04h,05h,01h 0 00000E63 150507FF db 15h,05h,07h,0FFh 0 00000E67 16040501 db 16h,04h,05h,01h 0 00000E6B 170B0402 db 17h,0Bh,04h,02h 0 00000E6F 18040501 db 18h,04h,05h,01h 0 00000E73 19050102 db 19h,05h,01h,02h 0 00000E77 1A0B0702 db 1Ah,0Bh,07h,02h 0 00000E7B 1B0B0402 db 1Bh,0Bh,04h,02h 0 00000E7F 1C020704 db 1Ch,02h,07h,04h 0 00000E83 1D0504FF db 1Dh,05h,04h,0FFh 0 00000E87 1E0504FF db 1Eh,05h,04h,0FFh 0 00000E8B 1F0D04FF db 1Fh,0Dh,04h,0FFh 0 00000E8F 200A0202 db 20h,0Ah,02h,02h 0 00000E93 210A0202 db 21h,0Ah,02h,02h 0 00000E97 220B0702 db 22h,0Bh,07h,02h 0 00000E9B 32090303 db 32h,09h,03h,03h 0 00000E9F 23070401 db 23h,07h,04h,01h 0 00000EA3 24010405 db 24h,01h,04h,05h 0 00000EA7 FF0D05FF db 0FFh,0Dh,05h,0FFh 726 727 org 0eabh - FIXED_DATA_START 728 729 ; This is a translation table from old error codes to extended errors 0 00000EAB 131415161718191A db 13h,14h,15h,16h,17h,18h,19h,1Ah 0 00000EB3 1B1C1D1E1F1F1F22 db 1Bh,1Ch,1Dh,1Eh,1Fh,1Fh,1Fh,22h 0 00000EBB 24 db 24h 733 734 735 ; KLUDGE for DRDOS 6.0 security - the word at offset zero in SYSDAT (the 736 ; SYStem DATa page) was the segment of the secure path string, with 737 ; a zero value indicating a non-secure system. 738 ; In order for DRDOS 6 level utilities to run we point SYSDAT at offset 739 ; 10h in the DOS data segment (this unused word is zero). On secure systems 740 ; the new LOGIN TSR will fix up both SYSDAT and the PD value to point to 741 ; it's own dummy SYSDAT, and the utilities will behave correctly. 742 743 Public @private_data 744 745 @private_data label byte ; We need some private data 0 00000EBC [0000] dw endOfInstanceData ; 0000 historical PD offset 0 00000EBE 0100 dummy_sysdat dw 1 ; 0002 historical SYSDAT segment 0 00000EC0 [3E01] dw offset histbuf1 ; 0004 History Control Block 1 0 00000EC2 [4401] dw offset histbuf2 ; 0006 History Control Block 2 0 00000EC4 00 @hist_flg db 0 ; 0008 History Control 751 ; Bit 0 = Buffer Select 1 = COMMAND 752 ; Bit 1 = History Enable 1 = ENABLE 0 00000EC5 01 db 1 ; 0009 Dual Language Version 0 00000EC6 00 db 0 ; 000A Current message language 0 00000EC7 0000 dw 0 ; 000B Extended memory 0 00000EC9 00 db 0 ; 000D (was # JMPF entries to fix up) 0 00000ECA 0000 codeSeg dw 0 ; 000E BDOS code segment (was seg of JMPF table) 0 00000ECC 0000 hmaRoot dw 0 ; 0010 Root of himem free chain 0 00000ECE 0000 dw 0 ; 0012 Initial Environment 0 00000ED0 0000 hmaAlloc dw 0 ; 0014 Root of himem allocation chain 0 00000ED2 0000 dmd_owner dw 0 ; 0016 Owner below which DMD's not freed 0 00000ED4 0000 dw 0 ; 0018 Link to upper memory DMD's 0 00000ED6 0000 LocalMachineID dw 0 ; 001A Patched by multi-tasker to correct value 0 00000ED8 0000 dmd_address dw 0 ; 001C Address below which DMD's not freed 0 00000EDA [3202] dw offset country_filename 0 00000EDC 00000000 hashptr dw 0,0 ; 0020 hash root 0 00000EE0 0000 hashmax dw 0 ; 0024 max dir entries hashed 0 00000EE2 0000 dw 0 ; 0026 was deblock seg 0 00000EE4 [520B] dw offset share_stub 770 ; 0028 share stub offset 0 00000EE6 [8601] dw offset globalPrivateData 772 ; 002A pointer to global private data 0 00000EE8 [E500] dw offset int2FBiosHandler 774 ; 002C pointer to int 2F internal hook 0 00000EEA 000000000000000000 dw 10 dup (0) ; space for expansion 0 00000EF3 000000000000000000 0 00000EFC 0000 776 777 Public deblock_seg, fdos_stub 778 0 00000EFE [0501] fdos_stub dw fdos_stub_entry 0 00000F00 0000 dw 0 ; fixup up at run time 781 0 00000F02 [0201]0000 share_stub dw invalid_stub,0 ; DWORD ptr to 15 0 00000F06 [0001]0000 dw nul_int,0 ; SHARE STUB routines 0 00000F0A [0001]0000 dw nul_int,0 ; 0 00000F0E [0001]0000 dw nul_int,0 ; 0 00000F12 [0001]0000 dw nul_int,0 ; 0 00000F16 [0001]0000 dw nul_int,0 ; 0 00000F1A [0001]0000 dw nul_int,0 ; 0 00000F1E [0001]0000 dw nul_int,0 ; 0 00000F22 [0001]0000 dw nul_int,0 ; 0 00000F26 [0001]0000 dw nul_int,0 ; 0 00000F2A [0201]0000 dw invalid_stub,0 ; 0 00000F2E [0001]0000 dw nul_int,0 ; 0 00000F32 [0001]0000 dw nul_int,0 ; 0 00000F36 [0001]0000 dw nul_int,0 ; 0 00000F3A [0001]0000 dw nul_int,0 ; 797 798 799 Public WindowsHandleCheck 0 00000F3E 26 WindowsHandleCheck db 26h ; MUST follow share_stub 801 ; patched by switcher 802 803 0 00000F3F 00 org 0FC0h - FIXED_DATA_START 805 0 00000FC0 0000 childSP dw 0 0 00000FC2 0000 childSS dw 0 0 00000FC4 0000 childIP dw 0 0 00000FC6 0000 childCS dw 0 810 811 ; The following table defines the format of a DOS .EXE format file. 812 ; The .EXE header is read into this data area and check for integrity 813 ; 814 Public exe_buffer 0 00000FC8 000000000000000000 exe_buffer db EXE_LENGTH dup (0) ; Local EXE header buffer 0 00000FD1 000000000000000000 0 00000FDA 000000000000000000 0 00000FE3 00 816 817 818 %if IDLE_DETECT 819 820 Public idle_data 821 Public active_cnt, idle_max 822 Public idle_flags, idle_vec 823 824 idle_data label word ; Idle State Data Area 0 00000FE4 0000 active_cnt dw 0 ; InActive Function Count 0 00000FE6 0A00 idle_max dw 10 ; Max No. of consecutive funcs. 0 00000FE8 0080 idle_flags dw IDLE_INIT ; $IDLE$ Has not been loaded 0 00000FEA 00000000 idle_vec dd 0 ; DWORD pointer to IDLE handler 829 830 831 Public int28_delay, int28_reload 0 00000FEE 0000 int28_delay dw 0 ; No. Consecutive INT28's 0 00000FF0 0A00 int28_reload dw 10 ; INT28 Delay Reload Value 0 00000FF2 [2103] dw indos_flag ; Offset of INDOS_FLAG 0 00000FF4 00000000 dw 2 dup (0) ; 2 OEM Reserved Words 836 %endif 837 0 00000FF8 00 org 1000h - FIXED_DATA_START ; nice 4K boundry 839 ; for multitasker 840 841 FIXED_DOS_DATA ends 842 === Switch to base=00C180h -> "PCMODE_DSIZE" 843 section PCMODE_DSIZE public align=16 class=DATA 844 845 Public data_end 846 data_end label word 847 848 PCMODE_DSIZE ends 849 850 851 extrn int20_entry:near, int21_entry:near 852 extrn int25_entry:near, int26_entry:near 853 extrn int27_entry:near, int2F_entry:near 854 extrn call5_entry:near 855 === Switch to base=00C180h -> "PCMODE_CODE" 856 section PCMODE_CODE public align=2 class=DATA 857 858 859 PCMODE_CODE_START equ 1000h 860 public MUSTBE1000 861 MUSTBE1000: 862 863 Public endOfInstanceData 864 865 endOfInstanceData label word 866 867 ;*** fixed data - init does segment fixups *** 868 869 stub_entries label word 870 871 Public lock_bios, unlock_bios, lock_tables, unlock_tables 872 0 00001000 [0701]0000 lock_bios dw lockbios,0 ; MSNET critical region stubs 0 00001004 [0D01]0000 unlock_bios dw unlockbios,0 ; MSNET critical region stubs 0 00001008 [1301]0000 lock_tables dw locktables,0 ; MSNET critical region stubs 0 0000100C [1901]0000 unlock_tables dw unlocktables,0 ; MSNET critical region stubs 877 878 Public exec_stub 0 00001010 [BF00]0000 exec_stub dw ExecStub,0 ; Int 21 EXEC hook 880 public func4B05_stub 0 00001014 [D000]0000 func4B05_stub dw Func4B05Stub,0 ; Int 21/4B05 hook 882 883 NUM_STUB_ENTRIES equ (offset $ - offset stub_entries)/4 884 ;*** fixed data ends *** 885 0 00001018 803E[2003]00 cmp byte [error_flag],0 ; JT-FAX uses this code sequence to 0 0000101D 75FE jnz $ ; find the address of the ERROR_FLAG 0 0000101F BC060A mov sp,0A06h 889 0 00001022 36F606[2003]FF test byte [ss:error_flag],0FFh ; SIDEKICK usues this fragment to 0 00001028 75FE jnz $ ; locate the ERROR_FLAG 0 0000102A 36FF36[5803] push word [ss:int28_flag] 0 0000102F CD28 int 28h 894 895 ;========================== 896 ; Entry points for DOS Code 897 ;========================== 898 ; 899 ; These are normally all of the form 900 ; 901 ;EntryPoint: 902 ; JMPF xxxx:RealEntryPoint 903 ; db 3 dup(?) 904 ; 905 ; When we are in the HMA, and so may disable the HMA during EXEC for EXEPACK 906 ; problems, we convert them to the following 907 ; 908 ;EntryPoint: 909 ; call A20Enable 910 ; JMPF xxxx:RealEntryPoint 911 ; 912 ; On an exec the A20 gate is disabled. This allows EXEPACKed programs to 913 ; unpack properly. (some exepacked apps have a wrap-round bug which addresses 914 ; the bottom 64K via the HMA). 915 ; 916 ; On the first Int 21 etc the A20Enable routine enables the A20 gate. 917 ; 918 919 FirstCodeEntryPoint label word 920 921 Int20Entry: 0 00001031 EA db 0EAh ; JMPF 0 00001032 [0000] dw int20_entry 0 00001034 0000000000 db 5 dup (0) ; filled in at run time 925 926 927 Int21Entry: 0 00001039 EA db 0EAh ; JMPF 0 0000103A [0000] dw int21_entry 0 0000103C 0000000000 db 5 dup (0) ; filled in at run time 931 932 Int25Entry: 0 00001041 EA db 0EAh ; JMPF 0 00001042 [0000] dw int25_entry 0 00001044 0000000000 db 5 dup (0) ; filled in at run time 936 937 Int26Entry: 0 00001049 EA db 0EAh ; JMPF 0 0000104A [0000] dw int26_entry 0 0000104C 0000000000 db 5 dup (0) ; filled in at run time 941 942 Int27Entry: 0 00001051 EA db 0EAh ; JMPF 0 00001052 [0000] dw int27_entry 0 00001054 0000000000 db 5 dup (0) ; filled in at run time 946 947 Int2FEntry: 0 00001059 EA db 0EAh ; JMPF 949 int2f_entry equ int2F_entry ; NASM port label 0 0000105A [0000] dw int2f_entry 0 0000105C 0000000000 db 5 dup (0) ; filled in at run time 952 953 Call5Entry: 0 00001061 EA db 0EAh ; JMPF 0 00001062 [0000] dw call5_entry 0 00001064 0000000000 db 5 dup (0) ; filled in at run time 957 958 LastCodeEntryPoint label word 959 960 961 BIOSA20Enable: 962 ;------------- 963 ; CALLF'd by the BIOS 0 00001069 E81200 call A20Enable ; do a near call 0 0000106C FB sti ; re-enable interrupts 0 0000106D CB retf ; RETF to BIOS 967 968 969 A20Disable: 970 ;---------- 971 ; On Entry: 972 ; DX = psp we are execing 0 0000106E 81FAF00F cmp dx,0FF0h ; if we are above 64K skip the 0 00001072 7309 jae A20Disable10 ; EXE pack kludge 0 00001074 50 push ax 0 00001075 B406 mov ah,6 ; disable the A20 gate during EXEC 0 00001077 2EFF1E[8201] call far [cs:xmsDriver] ; so buggy EXE packing will work 0 0000107C 58 pop ax 979 A20Disable10: 0 0000107D C3 ret 981 982 A20Enable: 983 ;--------- 984 ; On Entry: 985 ; None 986 ; WARNING - DS/ES/STACK could be anything 987 ; On Exit: 988 ; All regs preserved 989 ; 990 ; Unhook our Entry stubs so we don't get here again. 991 ; Enable the global A20 line to make the DOS/BIOS/COMMAND code visible 992 ; 0 0000107E FA cli 0 0000107F 50 push ax 0 00001080 1E push ds 0 00001081 B8FFFF mov ax,0FFFFh 0 00001084 8ED8 mov ds,ax 0 00001086 A19400 mov ax,[94h] ; is the HMA alias for Int 21 0 00001089 0B069600 or ax,[96h] ; zero - if so the HMA is there 0 0000108D 1F pop ds 0 0000108E 7502 jnz A20Enable10 0 00001090 58 pop ax 0 00001091 C3 ret 1004 1005 A20Enable10: 1006 ; We need to enable the A20 gate, go do so 0 00001092 53 push bx 0 00001093 2E8C16[B800] mov [cs:oldSS],ss ; save stack 0 00001098 2E8926[BA00] mov [cs:oldSP],sp 0 0000109D 8CC8 mov ax,cs 0 0000109F 8ED0 mov ss,ax ; swap to the error stack in case 0 000010A1 BC[F003] mov sp,offset error_stack ; 3rd part XMS driver needs a lot 1013 0 000010A4 B405 mov ah,5 ; enable A20, ignoring errors as we 0 000010A6 2EFF1E[8201] call far [cs:xmsDriver] ; can't do anything about them 1016 0 000010AB 2E8E16[B800] mov ss,[cs:oldSS] ; switch back to callers stack 0 000010B0 2E8B26[BA00] mov sp,[cs:oldSP] 1019 0 000010B5 5B pop bx 0 000010B6 58 pop ax 0 000010B7 C3 ret 1023 0 000010B8 0000 oldSS dw 0 ; save area for stack swap 0 000010BA 0000 oldSP dw 0 1026 1027 ; +++++++++++++++++++++++++++++++++ 1028 ; Default Int 24 Handler for DR DOS 1029 ; +++++++++++++++++++++++++++++++++ 1030 ; 1031 ; Our default critical error handler during boot simply FAIL's all 1032 ; critical errors. When COMMAND.COM is loaded this will install 1033 ; the "normal" Retry/Abort/Ignore handler. 1034 ; 1035 ; These interrupts normally point to an IRET. 1036 ; 1037 ; 1038 1039 Int24Entry: 1040 ;========== 0 000010BC B003 mov al,3 ; return "FAIL" 1042 DummyIRET: 1043 ;========= 0 000010BE CF iret 1045 1046 ; EXEC Code 1047 ; 1048 ; In order to cope with old buggy EXEPACKED programs we need to turn 1049 ; the A20 gate of during the exec, and turn it back on asap. 1050 ; To do this we hook all the DOS code entry points and re-enable the 1051 ; A20 whenever the app issues an Int 21 etc 1052 ; 1053 1054 1055 ExecStub: 1056 ;======== 1057 ; On Entry: 1058 ; AX = FCB validity flags 1059 ; DX = current PSP 1060 ; ES:SI -> new CS:IP 1061 ; CX:DI -> users stack 1062 ; On Exit: 1063 ; AX = FCB validity flags 1064 ; BX = 0 1065 ; SS:SP = users stack 1066 ; CS:IP = values from EXE header 1067 ; DS = ES = DX = current PSP 1068 ; 1069 ; When we start execing the application we have the A20 gate disabled so 1070 ; buggy EXE packed programs will unpack properly. 1071 ; We also hook Int 21 and Int 2F to re-enable the A20 gate on the first 1072 ; calls made to them. (These should only happen AFTER the unpacking). 1073 ; 1074 0 000010BF E8ACFF call A20Disable 0 000010C2 8ED1 mov ss,cx ; switch to new USER stack 0 000010C4 89FC mov sp,di 0 000010C6 06 push es 0 000010C7 56 push si ; CS:IP on USER stack 0 000010C8 8EDA mov ds,dx ; DS = ES = PSP we are exec'ing 0 000010CA 8EC2 mov es,dx 0 000010CC 31DB xor bx,bx ; BX = zero, set flags 0 000010CE FB sti 0 000010CF CB retf ; lets go! 1085 1086 Func4B05Stub: 1087 ;============ 1088 ; On Entry: 1089 ; ES:BP -> callers stack 1090 ; DX = PSP to exec on 1091 ; On Exit: 1092 ; callers registers restored 1093 ; 0 000010D0 E89BFF call A20Disable ; turn off A20 0 000010D3 8CC0 mov ax,es 0 000010D5 8ED0 mov ss,ax ; back to users stack 0 000010D7 89EC mov sp,bp 0 000010D9 585B595A5E5F5D1F07 POP_DOS ; Restore Registers 0 000010E2 CF iret 1100 1101 1102 Public int2FNext, int2FBiosHandler 1103 1104 Int2FBios: 1105 ;--------- 1106 ; On Entry: 1107 ; DS on stack 1108 ; On Exit: 1109 ; All regs preserved 1110 ; 1111 ; Pass on an Int 2F call to the BIOS 0 000010E3 1F pop ds ; recover DS and pass on to BIOS 0 000010E4 EA db 0EAh ; JMPF bios Int 2F entry point 0 000010E5 00000000 int2FBiosHandler dw 0,0 ; filled in at run time 0 000010E9 [E300]0000 int2FNext dw Int2FBios, 0 ; seg filled in at run time 1116 1117 1118 nul_strat: 0 000010ED 26807F0204 cmp byte [es:RH_CMD + bx],CMD_INPUT 0 000010F2 7506 jne nul_strat10 ; if it's input 0 000010F4 26C747120000 mov word [es:RH4_COUNT + bx],0 ; Say none transferred #IJ 1122 nul_strat10: 0 000010FA 26C747030001 mov word [es:RH_STATUS + bx],RHS_DONE ; Set the DONE bit in the 1124 nul_int: ; Request Header and Return 0 00001100 F8 clc ; (indicate success for SHARE) 0 00001101 CB retf 1127 1128 Public invalid_stub 1129 1130 invalid_stub: 0 00001102 B8FFFF mov ax,ED_FUNCTION ; indicate bad function 1132 fdos_stub_entry: 0 00001105 F9 stc ; indicate error 0 00001106 CB retf 1135 1136 Public lock_bios, unlock_bios, lock_tables, unlock_tables 1137 1138 lockbios: 1139 ;-------- 0 00001107 50 push ax 0 00001108 B80280 mov ax,8002h 0 0000110B EB10 jmp short CriticalSection 1143 1144 unlockbios: 1145 ;---------- 0 0000110D 50 push ax 0 0000110E B80281 mov ax,8102h 0 00001111 EB0A jmp short CriticalSection 1149 1150 locktables: 1151 ;---------- 0 00001113 50 push ax 0 00001114 B80180 mov ax,8001h 0 00001117 EB04 jmp short CriticalSection 1155 1156 unlocktables: 1157 ;------------ 0 00001119 50 push ax 0 0000111A B80181 mov ax,8101h 1160 ; jmps CriticalSection 1161 1162 CriticalSection: 1163 ;--------------- 1164 ; On Entry: 1165 ; AX = critical section number 1166 ; STACK = original AX 1167 ; On Exit: 1168 ; AX poped from stack 1169 ; 0 0000111D 2E803E[2901]00 cmp byte [cs:criticalSectionEnable],0 0 00001123 7402 je CriticalSection10 0 00001125 CD2A int 2ah ; issue critical section callout 1173 CriticalSection10: 0 00001127 58 pop ax 0 00001128 CB retf 1176 1177 public criticalSectionEnable 1178 0 00001129 00 criticalSectionEnable db 0 1180 1181 1182 Public SwStartupInfo 1183 0 0000112A 0300 SwStartupInfo dw 3 ; version 0 0000112C 0000 dw 0 0 0000112E 0000 dw 0 ; link to next in chain 1187 1188 ;; dw offset vxdName ; Virtual Dev file 1189 ;; replaced above line with DW 0 as vxd no longer required BAP 0 00001130 0000 dw 0 0 00001132 0000 dw 0 1192 0 00001134 00000000 dw 0,0 ; Reference Data 0 00001138 [3C01] dw offset instanceItems 0 0000113A 0000 instanceSeg dw 0 1196 1197 ;vxdName db 'A:\OPENDOS.386',0 1198 1199 public histbuf1, histsiz1, histbuf2, histsiz2 1200 1201 instanceItems: 0 0000113C 0000 dw 0 ; offset zero (for instancing) 0 0000113E 0000 histbuf1 dw 0 ; Command history buffer segment 0 00001140 0000 histsiz1 dw 0 ; size (in bytes) 1205 0 00001142 0000 dw 0 ; offset zero (for instancing) 0 00001144 0000 histbuf2 dw 0 ; Application history buffer segment 0 00001146 0000 histsiz2 dw 0 ; size (in bytes) 1209 1210 1211 ; some ROS fixups 0 00001148 000050000200 dw 000h,050h,002h ; BASIC variables 0 0000114E 0E0050001400 dw 00Eh,050h,014h ; BASIC variables 1214 1215 ; some BIOS fixups 0 00001154 B80070000400 dw 0B8h,070h,004h ; BIOS req_hdr 1217 ; dw 16Ch,070h,002h ; BIOS dev_no (no longer required) 0 0000115A 000670000200 dw 600h,070h,002h ; BIOS local_char 1219 1220 bdosInstanceFixups label word 0 00001160 [3200]00000400 dw con_device,0,4 ; CON: device ptr 0 00001166 [FB01]00000601 dw savbuf,0,column-savbuf+1 0 0000116C [8C00]00000200 dw dmd_upper_root,0,2 0 00001172 [8900]00000100 dw dmd_upper_link,0,1 0 00001178 [180C]00001C00 dw exe_buffer,0,EXE_LENGTH 1226 0 0000117E 00000000 dw 0,0 ; zero terminated instance list 1228 1229 0 00001182 00000000 xmsDriver dd 0 1231 1232 globalPrivateData: 0 00001186 00000000 dd 0 ; 0000 delwatch driver vector 0 0000118A 0000000000000000 dw 4 dup (0) ; space for expansion 1235 1236 1237 ;** COUNTRY INFO ** 1238 1239 1240 ; 1241 ; The following routines are called by the end user using the DWORD 1242 ; pointers in the Country Data. Each Country Data area contains a 1243 ; pointer to one of the following routines. All valid charcater 1244 ; codes above 7Fh are translated to Upper Case 1245 ; 1246 1247 Public xlat_xlat 1248 1249 xlat_xlat: 0 00001192 3C80 cmp al,080h 0 00001194 7209 jb xlat_exit 0 00001196 2C80 sub al,080h 0 00001198 53 push bx 1254 Standard_table equ standard_table ; NASM port label 0 00001199 BB[8107] mov bx,offset Standard_table 0 0000119C 2ED7 cs xlatb 0 0000119E 5B pop bx 1258 xlat_exit: 0 0000119F CB retf 1260 1261 1262 Public cur_country 1263 Public cur_cp 1264 Public default_country 1265 Public country_data 1266 Public Ucasetbl 1267 Public FileUcasetbl 1268 Public FileCharstbl 1269 Public Collatingtbl 1270 Public DBCS_tbl 1271 Public info1_len 1272 Public info2_len 1273 Public info4_len 1274 Public info5_len 1275 Public info6_len 1276 Public info7_len 1277 Public intl_xlat 1278 1279 ; table of pointers to default country info. pointed to in BDOS header 1280 Public NoYesChars 1281 0 000011A0 4E6E5979 NoYesChars db 'NnYy' 0 000011A4 [9202] dw country_data 0 000011A6 [9602] dw default_country 0 000011A8 [FD06] dw Ucasetbl 0 000011AA [7F07] dw FileUcasetbl 0 000011AC [0108] dw FileCharstbl 0 000011AE [3108] dw Collatingtbl 0 000011B0 [3309] dw DBCS_tbl 1290 1291 0 000011B2 00 org 11F0h - PCMODE_CODE_START 1293 1294 0 000011F0 FFFF dummy_fcbs dw 0ffffh ; terminate now 0 000011F2 0000 dw 0 0 000011F4 0100 dw 1 ; with one entry 1298 ; db DHNDL_LEN dup (0) ; this many bytes in it 1299 ; Commented out for NASM port (ecm) because the SFT entry 1300 ; structure has grown so large that the following org 1301 ; would overwrite the trail of the structure. This appears 1302 ; to be a fairly benign bug but NASM won't allow rewriting 1303 ; data it has already assembled, so we comment out this 1304 ; padding so that the correct number of zeroes is inserted. 1305 0 000011F6 00 org 1232h - PCMODE_CODE_START 1307 1308 Public country_filename 0 00001232 5C434F554E5452592E country_filename db '\COUNTRY.SYS' 0 0000123B 535953 1310 lengthof_country_filename equ $ - country_filename 0 0000123E 000000000000000000 db 64 - (lengthof_country_filename) dup (0) 0 00001247 000000000000000000 0 00001250 000000000000000000 0 00001259 000000000000000000 0 00001262 000000000000000000 0 0000126B 00000000000000 1312 0 00001272 00 org 1276h - PCMODE_CODE_START 1314 1315 ; We fix the country tables at this location for the benefit of 1316 ; LAN Manager 2.2 extended edition. It peeks directly rather than use 1317 ; int 21/65 ! 1318 1319 countryTable: 0 00001276 02 db 2 1321 UCasetbl equ Ucasetbl ; NASM port label 0 00001277 [FD06]0000 dw offset UCasetbl,0 0 0000127B 04 db 4 1324 FileUCasetbl equ FileUcasetbl ; NASM port label 0 0000127C [7F07]0000 dw offset FileUCasetbl,0 0 00001280 05 db 5 0 00001281 [0108]0000 dw offset FileCharstbl,0 0 00001285 06 db 6 0 00001286 [3108]0000 dw offset Collatingtbl,0 0 0000128A 07 db 7 0 0000128B [3309]0000 dw DBCS_tbl,0 0 0000128F 01 db 1 0 00001290 2600 dw 26h 1334 country_data: 0 00001292 0100 cur_country dw 1 ; Country Code 0 00001294 B501 cur_cp dw 437 ; Code Page 1337 default_country: 0 00001296 0000 dw US_DATE ; Date Format (Binary) 0 00001298 2400000000 db '$',0,0,0,0 ; Currency Symbol 0 0000129D 2C00 db ',',0 ; Thousands Separator 0 0000129F 2E00 db '.',0 ; Decimal Separator 0 000012A1 2D00 db '-',0 ; Date Separator 0 000012A3 3A00 db ':',0 ; Time Separator 0 000012A5 00 db 0 ; Symbol before Value without Space ($n.nn) 0 000012A6 02 db 2 ; Significant Currency Digits 0 000012A7 00 db CLOCK_12 ; Time Format 0 000012A8 [9201] intl_xlat dw xlat_xlat ; Case Translation Routine 0 000012AA 0000 dw 0000h ; Case Translation Segment (Runtime Fixup) 0 000012AC 2C00 db ',',0 ; Data List Separator 1350 info1_len equ (offset $ - offset country_data) 1351 ; If NOT COUNTRY.SYS then include the 0 000012AE 000000000000000000 db 10 dup (0) ; 10 zero bytes held at the end of the 0 000012B7 00 1353 ; country information. 1354 1355 1356 PCMODE_CODE ends 1357 === Switch to base=000000h -> "PCM_CODEND" 1358 section PCM_CODEND public align=16 class=CODE 1359 1360 Public code_end 1361 code_end label byte 1362 1363 PCM_CODEND ends 1364 === Switch to base=00C180h -> "BDOS_DATA" 1365 section BDOS_DATA public align=2 class=DATA 1366 1367 Public hashroot, hashmax 1368 1369 ; The hashroot must be global, but we also need to make it accessible 1370 ; during CONFIG so we copy it from the private data area 1371 0 000012CC 00000000 hashroot dw 0,0 1373 1374 1375 Public lfn_find_handles 1376 Public lfn_find_handles_end 1377 lfn_find_handles: 0 000012D0 000000000000000000 dw 32 dup (0) 0 000012D9 000000000000000000 0 000012E2 000000000000000000 0 000012EB 000000000000000000 0 000012F4 000000000000000000 0 000012FD 000000000000000000 0 00001306 000000000000000000 0 0000130F 00 1379 lfn_find_handles_end: 1380 1381 Public lfn_find_handle_heap 1382 Public lfn_find_handle_heap_end 1383 lfn_find_handle_heap: 0 00001310 000000000000000000 db 2Eh * 32 dup (0) 0 00001319 000000000000000000 0 00001322 000000000000000000 0 0000132B 000000000000000000 0 00001334 000000000000000000 0 0000133D 000000000000000000 0 00001346 000000000000000000 0 0000134F 000000000000000000 0 00001358 000000000000000000 0 00001361 000000000000000000 0 0000136A 000000000000000000 0 00001373 000000000000000000 0 0000137C 000000000000000000 0 00001385 000000000000000000 0 0000138E 000000000000000000 0 00001397 000000000000000000 0 000013A0 000000000000000000 0 000013A9 000000000000000000 0 000013B2 000000000000000000 0 000013BB 000000000000000000 0 000013C4 000000000000000000 0 000013CD 000000000000000000 0 000013D6 000000000000000000 0 000013DF 000000000000000000 0 000013E8 000000000000000000 0 000013F1 000000000000000000 0 000013FA 000000000000000000 0 00001403 000000000000000000 0 0000140C 000000000000000000 0 00001415 000000000000000000 0 0000141E 000000000000000000 0 00001427 000000000000000000 0 00001430 000000000000000000 0 00001439 000000000000000000 0 00001442 000000000000000000 0 0000144B 000000000000000000 0 00001454 000000000000000000 0 0000145D 000000000000000000 0 00001466 000000000000000000 0 0000146F 000000000000000000 0 00001478 000000000000000000 0 00001481 000000000000000000 0 0000148A 000000000000000000 0 00001493 000000000000000000 0 0000149C 000000000000000000 0 000014A5 000000000000000000 0 000014AE 000000000000000000 0 000014B7 000000000000000000 0 000014C0 000000000000000000 0 000014C9 000000000000000000 0 000014D2 000000000000000000 0 000014DB 000000000000000000 0 000014E4 000000000000000000 0 000014ED 000000000000000000 0 000014F6 000000000000000000 0 000014FF 000000000000000000 0 00001508 000000000000000000 0 00001511 000000000000000000 0 0000151A 000000000000000000 0 00001523 000000000000000000 0 0000152C 000000000000000000 0 00001535 000000000000000000 0 0000153E 000000000000000000 0 00001547 000000000000000000 0 00001550 000000000000000000 0 00001559 000000000000000000 0 00001562 000000000000000000 0 0000156B 000000000000000000 0 00001574 000000000000000000 0 0000157D 000000000000000000 0 00001586 000000000000000000 0 0000158F 000000000000000000 0 00001598 000000000000000000 0 000015A1 000000000000000000 0 000015AA 000000000000000000 0 000015B3 000000000000000000 0 000015BC 000000000000000000 0 000015C5 000000000000000000 0 000015CE 000000000000000000 0 000015D7 000000000000000000 0 000015E0 000000000000000000 0 000015E9 000000000000000000 0 000015F2 000000000000000000 0 000015FB 000000000000000000 0 00001604 000000000000000000 0 0000160D 000000000000000000 0 00001616 000000000000000000 0 0000161F 000000000000000000 0 00001628 000000000000000000 0 00001631 000000000000000000 0 0000163A 000000000000000000 0 00001643 000000000000000000 0 0000164C 000000000000000000 0 00001655 000000000000000000 0 0000165E 000000000000000000 0 00001667 000000000000000000 0 00001670 000000000000000000 0 00001679 000000000000000000 0 00001682 000000000000000000 0 0000168B 000000000000000000 0 00001694 000000000000000000 0 0000169D 000000000000000000 0 000016A6 000000000000000000 0 000016AF 000000000000000000 0 000016B8 000000000000000000 0 000016C1 000000000000000000 0 000016CA 000000000000000000 0 000016D3 000000000000000000 0 000016DC 000000000000000000 0 000016E5 000000000000000000 0 000016EE 000000000000000000 0 000016F7 000000000000000000 0 00001700 000000000000000000 0 00001709 000000000000000000 0 00001712 000000000000000000 0 0000171B 000000000000000000 0 00001724 000000000000000000 0 0000172D 000000000000000000 0 00001736 000000000000000000 0 0000173F 000000000000000000 0 00001748 000000000000000000 0 00001751 000000000000000000 0 0000175A 000000000000000000 0 00001763 000000000000000000 0 0000176C 000000000000000000 0 00001775 000000000000000000 0 0000177E 000000000000000000 0 00001787 000000000000000000 0 00001790 000000000000000000 0 00001799 000000000000000000 0 000017A2 000000000000000000 0 000017AB 000000000000000000 0 000017B4 000000000000000000 0 000017BD 000000000000000000 0 000017C6 000000000000000000 0 000017CF 000000000000000000 0 000017D8 000000000000000000 0 000017E1 000000000000000000 0 000017EA 000000000000000000 0 000017F3 000000000000000000 0 000017FC 000000000000000000 0 00001805 000000000000000000 0 0000180E 000000000000000000 0 00001817 000000000000000000 0 00001820 000000000000000000 0 00001829 000000000000000000 0 00001832 000000000000000000 0 0000183B 000000000000000000 0 00001844 000000000000000000 0 0000184D 000000000000000000 0 00001856 000000000000000000 0 0000185F 000000000000000000 0 00001868 000000000000000000 0 00001871 000000000000000000 0 0000187A 000000000000000000 0 00001883 000000000000000000 0 0000188C 000000000000000000 0 00001895 000000000000000000 0 0000189E 000000000000000000 0 000018A7 000000000000000000 0 000018B0 000000000000000000 0 000018B9 000000000000000000 0 000018C2 000000000000000000 0 000018CB 0000000000 1385 lfn_find_handle_heap_end: 1386 1387 Public lfn_find_handle_heap_free 1388 lfn_find_handle_heap_free: 0 000018D0 [4400] dw lfn_find_handle_heap 1390 1391 Public lfnpathflag 1392 lfnpathflag: 0 000018D2 00 db 0 1394 Public lfn_search_redir 1395 lfn_search_redir: 0 000018D3 00 db 0 ; lfn.asm expects this directly after lfnpathflag 1397 1398 BDOS_DATA ends 1399 1400 === Switch to base=000000h -> "PCM_HISTORY" 1401 section PCM_HISTORY public align=1 class=CODE 1402 0 0000BB42 6606 patch_area dw 0666h 0 0000BB44 909090909090909090 db 256 dup (090h) 0 0000BB4D 909090909090909090 0 0000BB56 909090909090909090 0 0000BB5F 909090909090909090 0 0000BB68 909090909090909090 0 0000BB71 909090909090909090 0 0000BB7A 909090909090909090 0 0000BB83 909090909090909090 0 0000BB8C 909090909090909090 0 0000BB95 909090909090909090 0 0000BB9E 909090909090909090 0 0000BBA7 909090909090909090 0 0000BBB0 909090909090909090 0 0000BBB9 909090909090909090 0 0000BBC2 909090909090909090 0 0000BBCB 909090909090909090 0 0000BBD4 909090909090909090 0 0000BBDD 909090909090909090 0 0000BBE6 909090909090909090 0 0000BBEF 909090909090909090 0 0000BBF8 909090909090909090 0 0000BC01 909090909090909090 0 0000BC0A 909090909090909090 0 0000BC13 909090909090909090 0 0000BC1C 909090909090909090 0 0000BC25 909090909090909090 0 0000BC2E 909090909090909090 0 0000BC37 909090909090909090 0 0000BC40 90909090 1405 1406 PCM_HISTORY ends 1407 === Switch to base=000000h -> "PCM_ICODE" 1408 section PCM_ICODE public align=1 class=CODE 1409 1410 ; 1411 ; The following routine initializes all the standard MS-DOS interrupt 1412 ; vectors which are initialized to point to the PC-MODE handlers. 1413 ; 1414 ; Entry: AX Memory Size - Paragraphs 1415 ; BX First Available Paragraph 1416 ; DL Initial Drive 1417 ; DS PCM Dseg 1418 ; ES Interrupt Stubs Seg 1419 ; 1420 pcmode_init: 0 0000BED9 2E8C06[A102] mov [cs:int_stubs_seg],es 0 0000BEDE 2E8126[2238]FFF7 and word [cs:patch_version],~ DOSINROM 1423 ; won't clear if we are in ROM... 0 0000BEE5 2E8C1E[0638] mov [cs:pcmode_dseg],ds ; save PCM Dseg 0 0000BEEA 8C1E[3A01] mov [instanceSeg],ds ; fixup pointer to instance items 1426 1427 ; removed this as VxD no longer required BAP 1428 ; mov ds:vxdNameSeg,ds ; and vxdName 1429 1430 ; add ds:vxdName,dl ; fixup drive letter 0 0000BEEE 8C1E[3A00] mov word ptr [buf_ptr+2],ds 0 0000BEF2 8C1E[2C00] mov word ptr [file_ptr+2],ds 0 0000BEF6 8C1E[4200] mov word ptr [fcb_ptr+2],ds 0 0000BEFA 50 push ax ; Save the memory size 0 0000BEFB 53 push bx ; First Free Paragraph 0 0000BEFC 8816[3603] mov [current_dsk],dl ; save initial drive 0 0000BF00 FEC2 inc dl ; make drive one based 0 0000BF02 8816[6900] mov [bootDrv],dl ; and save for func 3305 0 0000BF06 8CD8 mov ax,ds ; AX = PCMode Data 0 0000BF08 A3[500B] mov word ptr [fdos_stub+2],ax 0 0000BF0B 0106[0E0B] add [dummy_sysdat],ax ; point dummy "sysdat" at a zero word 1442 ; ie. dummy "secure path" segment 0 0000BF0F BE[7602] mov si,offset countryTable 1444 countryFixupLoop: 0 0000BF12 8C5C03 mov word ptr [3 + si],ds ; fixup the segment 0 0000BF15 83C605 add si,5 ; onto the next entry 0 0000BF18 837C0300 cmp word ptr [3 + si],0 ; done the lot yet ? 0 0000BF1C 74F4 je countryFixupLoop 0 0000BF1E 8EC0 mov es,ax ; ES -> PCMode Data 0 0000BF20 BF[0000] mov di,offset stub_entries ; ES:DI -> stub segs 0 0000BF23 B90600 mov cx,NUM_STUB_ENTRIES ; entries to initialise 1452 stubs_loop: 0 0000BF26 83C702 add di,2 ; skip the offset 0 0000BF29 AB stosw ; fixup segment 0 0000BF2A E2FA loop stubs_loop ; do the next one 0 0000BF2C BF[520B] mov di,offset share_stub ; fixup the SHARE entries 0 0000BF2F B90F00 mov cx,NUM_SHARE_STUB_ENTRIES 1458 share_loop: 0 0000BF32 83C702 add di,2 ; skip the offset 0 0000BF35 AB stosw ; fixup segment 0 0000BF36 E2FA loop share_loop 1462 ; mov cx,0 0 0000BF38 8EC1 mov es,cx ; Initialize the DOS vectors 1464 0 0000BF3A 26A1BC00 mov ax,[es:INT2F_OFFSET] ; remember address of BIOS Int 2F 0 0000BF3E A3[E500] mov [int2FBiosHandler],ax 0 0000BF41 26A1BE00 mov ax,[es:INT2F_SEGMENT] 0 0000BF45 A3[E700] mov [int2FBiosHandler+2],ax 0 0000BF48 8C1E[EB00] mov [int2FNext+2],ds ; fixup seg of out stub 1470 0 0000BF4C B91600 mov cx,40h-2Ah ; 2A-3F point at IRET in DOS Data Seg 0 0000BF4F BFA800 mov di,INT2A_OFFSET 0 0000BF52 2E8B2E[A102] mov bp,[cs:int_stubs_seg] 0 0000BF57 31DB xor bx,bx 1475 dummy_vecs_loop: 0 0000BF59 83F90F cmp cx,40h-31h 0 0000BF5C 741D je dummy_vecs_skip 0 0000BF5E 06 push es 0 0000BF5F 8EC5 mov es,bp 0 0000BF61 26C607EA mov byte ptr [es:bx],0eah ; jmp far instruction 0 0000BF65 B8[BE00] mov ax,offset DummyIRET ; point at an IRET 1482 ; stosw ; do the offset 0 0000BF68 26894701 mov [es:1 + bx],ax 1484 ; mov ax,ds 1485 ; stosw ; then the segment 0 0000BF6C 268C5F03 mov [es:3 + bx],ds 0 0000BF70 07 pop es 0 0000BF71 26891D mov [es:di],bx 0 0000BF74 26896D02 mov [es:2 + di],bp 0 0000BF78 83C305 add bx,5 1491 dummy_vecs_skip: 0 0000BF7B 83C704 add di,4 0 0000BF7E E2D9 loop dummy_vecs_loop 1494 1495 0 0000BF80 BE[7502] mov si,offset def_data_vecs ; the following vector point to 0 0000BF83 B90B00 mov cx,no_def_data_vecs ; pcmode DATA seg 1498 def_data_vecs_loop: 0 0000BF86 06 push es 0 0000BF87 8EC5 mov es,bp 0 0000BF89 2EAD cs lodsw 0 0000BF8B 89C7 mov di,ax ; Get the Vector Offset (from CS) 1503 ; db 2Eh ; CS: 1504 ; movsw ; copy service routine offset 0 0000BF8D 26C607EA mov byte ptr [es:bx],0eah ; jmp far 0 0000BF91 2E8B04 mov ax,[cs:si] 0 0000BF94 83C602 add si,2 0 0000BF97 26894701 mov [es:1 + bx],ax 0 0000BF9B 8CD8 mov ax,ds ; finally fixup the segment too 1510 ; stosw 0 0000BF9D 26894703 mov [es:3 + bx],ax 0 0000BFA1 07 pop es 0 0000BFA2 89D8 mov ax,bx 0 0000BFA4 AB stosw 0 0000BFA5 89E8 mov ax,bp 0 0000BFA7 AB stosw 0 0000BFA8 83C305 add bx,5 0 0000BFAB E2D9 loop def_data_vecs_loop 1519 0 0000BFAD 26C606C000EA mov byte [es:INT30_OFFSET],0EAh 1521 ; fixup CALL 5 JMPF 1522 0 0000BFB3 BE[6001] mov si,offset bdosInstanceFixups 1524 InstanceFixupLoop: 0 0000BFB6 8C5C02 mov [2 + si],ds ; fixup data segment 0 0000BFB9 83C606 add si,6 ; onto next item 0 0000BFBC 8B04 mov ax,[si] ; still BDOS ? 0 0000BFBE 0B4402 or ax,[2 + si] 0 0000BFC1 75F3 jnz InstanceFixupLoop ; yep, do another one 1530 0 0000BFC3 0E push cs ; we will have a RETF 0 0000BFC4 E8DF00 call pcmode_reinit ; to return from this call 1533 0 0000BFC7 58 pop ax ; First Free Paragraph 0 0000BFC8 5A pop dx ; Restore the BIOS memory size 0 0000BFC9 29C2 sub dx,ax ; convert to TPA size 0 0000BFCB 4A dec dx ; Decrement the Size by DMD Size 0 0000BFCC 50 push ax 0 0000BFCD 01D0 add ax,dx ; AX = possible next DMD 0 0000BFCF 8EC0 mov es,ax 0 0000BFD1 B05A mov al,IDZ ; assume no extra DMD's 0 0000BFD3 263A060000 cmp al,[es:DMD_ID] ; have we extra one ? 0 0000BFD8 7503 jne pcmode_init10 0 0000BFDA B04D mov al,IDM ; yes, no longer end of chain 0 0000BFDC 4A dec dx ; decrement by size of existing DMD 1546 pcmode_init10: 0 0000BFDD 07 pop es 0 0000BFDE 26A20000 mov [es:DMD_ID],al ; Last DMD in list 0 0000BFE2 26C70601000000 mov word [es:DMD_PSP],0000h ; This is Free Memory Owning PSP == 0 0 0000BFE9 2689160300 mov [es:DMD_LEN],dx ; Save Memory Length 0 0000BFEE 26C70608005344 mov word [es:DMD_NAME],'S'+256*'D' 0 0000BFF5 26C6060A0000 mov byte [es:DMD_NAME+2],0 0 0000BFFB 8C06[2400] mov [dmd_root],es ; Save the DMD address in root 0 0000BFFF CB retf 1555 1556 ; Entry: DS PCM Dseg 1557 ; ES Interrupt Stubs Seg 1558 1559 pcmode_init2: 0 0000C000 2E8C06[A102] mov [cs:int_stubs_seg],es 1561 ; and cs:patch_version,not DOSINROM 1562 ; won't clear if we are in ROM... 0 0000C005 2E8C1E[0638] mov [cs:pcmode_dseg],ds ; save PCM Dseg 0 0000C00A 8C1E[3A01] mov [instanceSeg],ds ; fixup pointer to instance items 1565 1566 ; removed this as VxD no longer required BAP 1567 ; mov ds:vxdNameSeg,ds ; and vxdName 1568 1569 ; add ds:vxdName,dl ; fixup drive letter 0 0000C00E 8C1E[3A00] mov word ptr [buf_ptr+2],ds 0 0000C012 8C1E[2C00] mov word ptr [file_ptr+2],ds 0 0000C016 8C1E[4200] mov word ptr [fcb_ptr+2],ds 0 0000C01A A1[4000] mov ax,word ptr [fcb_ptr] 0 0000C01D B104 mov cl,4 0 0000C01F D3E8 shr ax,cl 0 0000C021 8326[4000]0F and word [fcb_ptr],15 0 0000C026 0106[4200] add word ptr [fcb_ptr+2],ax 1578 ; push ax ; Save the memory size 1579 ; push bx ; First Free Paragraph 1580 ; mov ds:current_dsk,dl ; save initial drive 1581 ; inc dl ; make drive one based 1582 ; mov ds:bootDrv,dl ; and save for func 3305 0 0000C02A 8CD8 mov ax,ds ; AX = PCMode Data 0 0000C02C A3[500B] mov word ptr [fdos_stub+2],ax 0 0000C02F 0106[0E0B] add [dummy_sysdat],ax ; point dummy "sysdat" at a zero word 1586 ; ie. dummy "secure path" segment 0 0000C033 BE[7602] mov si,offset countryTable 1588 countryFixupLoop2: 0 0000C036 8C5C03 mov word ptr [3 + si],ds ; fixup the segment 0 0000C039 83C605 add si,5 ; onto the next entry 0 0000C03C 837C0300 cmp word ptr [3 + si],0 ; done the lot yet ? 0 0000C040 74F4 je countryFixupLoop2 0 0000C042 8EC0 mov es,ax ; ES -> PCMode Data 0 0000C044 BF[0000] mov di,offset stub_entries ; ES:DI -> stub segs 0 0000C047 B90600 mov cx,NUM_STUB_ENTRIES ; entries to initialise 1596 stubs_loop2: 0 0000C04A 83C702 add di,2 ; skip the offset 0 0000C04D AB stosw ; fixup segment 0 0000C04E E2FA loop stubs_loop2 ; do the next one 0 0000C050 BF[520B] mov di,offset share_stub ; fixup the SHARE entries 0 0000C053 B90F00 mov cx,NUM_SHARE_STUB_ENTRIES 1602 share_loop2: 0 0000C056 83C702 add di,2 ; skip the offset 0 0000C059 AB stosw ; fixup segment 0 0000C05A E2FA loop share_loop2 1606 ; mov cx,0 0 0000C05C 8EC1 mov es,cx ; Initialize the DOS vectors 1608 1609 ; mov ax,es:.INT2F_OFFSET ; remember address of BIOS Int 2F 1610 ; mov ds:int2FBiosHandler,ax 1611 ; mov ax,es:.INT2F_SEGMENT 1612 ; mov ds:int2FBiosHandler+2,ax 0 0000C05E 8C1E[EB00] mov [int2FNext+2],ds ; fixup seg of out stub 1614 0 0000C062 B91600 mov cx,40h-2Ah ; 2A-3F point at IRET in DOS Data Seg 0 0000C065 BFA800 mov di,INT2A_OFFSET 0 0000C068 2E8B2E[A102] mov bp,[cs:int_stubs_seg] 0 0000C06D 31DB xor bx,bx 0 0000C06F 06 push es 0 0000C070 8EC5 mov es,bp 1621 dummy_vecs_loop2: 0 0000C072 83F90F cmp cx,40h-31h 0 0000C075 7407 je dummy_vecs_skip2 1624 ; mov ax,offset DummyIRET ; point at an IRET 1625 ; stosw ; do the offset 1626 ; mov ax,ds 0 0000C077 268C5F03 mov [es:3 + bx],ds 1628 ; stosw ; then the segment 0 0000C07B 83C305 add bx,5 1630 dummy_vecs_skip2: 0 0000C07E E2F2 loop dummy_vecs_loop2 0 0000C080 07 pop es 1633 1634 ; mov si,offset def_data_vecs ; the following vector point to 0 0000C081 B90B00 mov cx,no_def_data_vecs ; pcmode DATA seg 0 0000C084 06 push es 0 0000C085 8EC5 mov es,bp 1638 def_data_vecs_loop2: 1639 ; lods cs:ax ! mov di,ax ; Get the Vector Offset (from CS) 1640 ; mov ax,[cs:si] 1641 ; db 2Eh ; CS: 1642 ; movsw ; copy service routine offset 1643 ; mov ax,ds ; finally fixup the segment too 1644 ; stosw 0 0000C087 268C5F03 mov [es:3 + bx],ds 0 0000C08B 83C305 add bx,5 0 0000C08E E2F7 loop def_data_vecs_loop2 0 0000C090 07 pop es 1649 1650 ; mov es:byte ptr .INT30_OFFSET,0EAh 1651 ; fixup CALL 5 JMPF 1652 0 0000C091 BE[6001] mov si,offset bdosInstanceFixups 1654 InstanceFixupLoop2: 0 0000C094 8C5C02 mov [2 + si],ds ; fixup data segment 0 0000C097 83C606 add si,6 ; onto next item 0 0000C09A 8B04 mov ax,[si] ; still BDOS ? 0 0000C09C 0B4402 or ax,[2 + si] 0 0000C09F 75F3 jnz InstanceFixupLoop2 ; yep, do another one 1660 0 0000C0A1 0E push cs ; we will have a RETF 0 0000C0A2 E80100 call pcmode_reinit ; to return from this call 1663 1664 ; pop ax ; First Free Paragraph 1665 ; pop dx ; Restore the BIOS memory size 1666 ; sub dx,ax ; convert to TPA size 1667 ; dec dx ; Decrement the Size by DMD Size 1668 ; push ax 1669 ; add ax,dx ; AX = possible next DMD 1670 ; mov es,ax 1671 ; mov al,IDZ ; assume no extra DMD's 1672 ; cmp al,es:DMD_ID ; have we extra one ? 1673 ; jne pcmode_init2_10 1674 ; mov al,IDM ; yes, no longer end of chain 1675 ; dec dx ; decrement by size of existing DMD 1676 ;pcmode_init2_10: 1677 ; pop es 1678 ; mov es:DMD_ID,al ; Last DMD in list 1679 ; mov es:DMD_PSP,0000h ; This is Free Memory Owning PSP == 0 1680 ; mov es:DMD_LEN,dx ; Save Memory Length 1681 ; mov es:word ptr DMD_NAME,'S'+256*'D' 1682 ; mov es:DMD_NAME+2,0 1683 ; mov ds:dmd_root,es ; Save the DMD address in root 0 0000C0A5 CB retf 1685 1686 ; 1687 ; 1688 ; On Entry: 1689 ; DS = DOS data seg 1690 1691 pcmode_reinit: 1692 ;============= 0 0000C0A6 8C1E[AA02] mov word ptr [intl_xlat+2],ds 1694 ; fixup intl case routine 0 0000C0AA 8C0E[1A0B] mov [codeSeg],cs ; fixup code segment 1696 1697 0 0000C0AE A1[2C0B] mov ax,[hashptr] ; make a copy of the hashroot 0 0000C0B1 A3[0000] mov [hashroot],ax ; so it's global 0 0000C0B4 A1[2E0B] mov ax,[hashptr+2] 0 0000C0B7 A3[0200] mov [hashroot+2],ax 0 0000C0BA A0[140B] mov al,[@hist_flg] ; get initial history flags 0 0000C0BD 83E007 and ax,RLF_ENHANCED+RLF_INS+RLF_SEARCH 0 0000C0C0 A3[FA06] mov [cle_state],ax ; use to set initial editing state 1705 0 0000C0C3 C706[8201][0201] mov word [xmsDriver],offset invalid_stub 0 0000C0C9 8C1E[8401] mov word ptr [xmsDriver+2],ds 1708 0 0000C0CD BB[3100] mov bx,offset FirstCodeEntryPoint 1710 pcmode_reinit10: 0 0000C0D0 8C4F03 mov [3 + bx],cs ; fixup segment of the JMPF 0 0000C0D3 83C308 add bx,8 ; onto the next one 0 0000C0D6 81FB[6900] cmp bx,offset LastCodeEntryPoint 0 0000C0DA 72F4 jb pcmode_reinit10 0 0000C0DC A1[1C0B] mov ax,[hmaRoot] ; have we established an HMA free chain 0 0000C0DF 0B06[200B] or ax,[hmaAlloc] ; or have any registered users ? 0 0000C0E3 7468 jz pcmode_reinit30 ; if so hook for EXEPACK support 0 0000C0E5 B80043 mov ax,4300h 0 0000C0E8 CD2F int 2Fh ; do we have an XMS driver ? 0 0000C0EA 3C80 cmp al,80h ; 80h says yes 0 0000C0EC 755F jne pcmode_reinit30 0 0000C0EE B81043 mov ax,4310h ; get it's entry point 0 0000C0F1 CD2F int 2Fh ; in ES:BX 0 0000C0F3 891E[8201] mov word ptr [xmsDriver],bx 0 0000C0F7 8C06[8401] mov word ptr [xmsDriver+2],es 1726 0 0000C0FB B8FFFF mov ax,0FFFFh 0 0000C0FE 8EC0 mov es,ax 0 0000C100 40 inc ax ; AX = 0 0 0000C101 26A39400 mov [es:94h],ax ; zero the HMA alias for Int 21 0 0000C105 26A39600 mov [es:96h],ax ; we use this as our A20 gate test 1732 0 0000C109 BB[3100] mov bx,offset FirstCodeEntryPoint 1734 pcmode_reinit20: 0 0000C10C B8[7B00] mov ax,offset A20Enable-3 ; we need a relative offset to 0 0000C10F 29D8 sub ax,bx ; poke in a "call A20Enable" 0 0000C111 874701 xchg ax,[1 + bx] ; pick up the entry point segment 0 0000C114 C607E8 mov byte ptr [0 + bx],0E8h ; CALL NEAR 0 0000C117 C64703EA mov byte ptr [3 + bx],0EAh ; JMPF 0 0000C11B 894704 mov [4 + bx],ax ; fixup the offset 0 0000C11E 8C4F06 mov [6 + bx],cs ; fixup the segment 0 0000C121 83C308 add bx,8 ; ready to do the next entry 0 0000C124 81FB[6900] cmp bx,offset LastCodeEntryPoint 0 0000C128 72E2 jb pcmode_reinit20 1745 0 0000C12A B87000 mov ax,70h ; now fixup the BIOS A20 Enable 0 0000C12D 8EC0 mov es,ax 0 0000C12F 31FF xor di,di ; patch entry point at 70:0 0 0000C131 B09A mov al,09Ah ; CALLF 0 0000C133 AA stosb 0 0000C134 B8[6900] mov ax,offset BIOSA20Enable 0 0000C137 AB stosw ; offset 0 0000C138 8CD8 mov ax,ds 0 0000C13A AB stosw ; seg 0 0000C13B B0C3 mov al,0C3h 0 0000C13D AA stosb ; RET 1757 0 0000C13E 813E[1A0B]00F0 cmp word [codeSeg],0F000h ; have we relocated DOS into the HMA ? 0 0000C144 7207 jb pcmode_reinit30 ; if so we must remember it 0 0000C146 2E810E[2238]0010 or word [cs:patch_version],DOSINHMA 1761 pcmode_reinit30: 0 0000C14D CB retf 1763 1764 1765 def_data_vecs label word 0 0000C14E 8800[BE00] dw INT22_OFFSET, DummyIRET 0 0000C152 8C00[BE00] dw INT23_OFFSET, DummyIRET 0 0000C156 9000[BC00] dw INT24_OFFSET, Int24Entry 0 0000C15A A000[BE00] dw INT28_OFFSET, DummyIRET 1770 0 0000C15E 8000[3100] dw INT20_OFFSET, Int20Entry 0 0000C162 8400[3900] dw INT21_OFFSET, Int21Entry 0 0000C166 9400[4100] dw INT25_OFFSET, Int25Entry 0 0000C16A 9800[4900] dw INT26_OFFSET, Int26Entry 0 0000C16E 9C00[5100] dw INT27_OFFSET, Int27Entry 0 0000C172 BC00[5900] dw INT2F_OFFSET, Int2FEntry 0 0000C176 C100[6100] dw INT30_OFFSET+1,Call5Entry 1778 1779 1780 no_def_data_vecs equ (offset $ - offset def_data_vecs)/4 1781 0 0000C17A 0000 int_stubs_seg dw 0 1783 1784 PCM_ICODE ends 1785 1786 end 1787 === Trace listing source: drdos/bin/pcmif.lst 1 ; File : $PCMIF.ASM$ 2 ; 3 ; Description : 4 ; 5 ; Original Author : DIGITAL RESEARCH 6 ; 7 ; Last Edited By : $CALDERA$ 8 ; 9 ;-----------------------------------------------------------------------; 10 ; Copyright Work of Caldera, Inc. All Rights Reserved. 11 ; 12 ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, 13 ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. 14 ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES 15 ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF 16 ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO 17 ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE 18 ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE 19 ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, 20 ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, 21 ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, 22 ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF 23 ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT 24 ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND 25 ; CIVIL LIABILITY. 26 ;-----------------------------------------------------------------------; 27 ; 28 ; *** Current Edit History *** 29 ; *** End of Current Edit History *** 30 ; 31 ; $Log: $ 32 ; PCMIF.A86 1.21 93/09/09 22:36:50 33 ; Int 21/59 uses error stack 34 ; PCMIF.A86 1.20 93/08/27 18:56:30 35 ; Int 25/26 32 bit sector detection 36 ; PCMIF.A86 1.19 93/07/22 19:30:54 37 ; chnage int 25/26 support for NDD 38 ; PCMIF.A86 1.18 93/07/20 22:47:54 39 ; Even fewer checks on int 25/26 40 ; PCMIF.A86 1.14 93/05/06 19:28:31 41 ; Move int 23/28 support to CIO. 42 ; PCMIF.A86 1.13 93/05/05 23:31:0 43 ; int 2A/84 is now only generated on input-and-wait functions 44 ; PCMIF.A86 1.12 93/03/25 15:06:48 45 ; tweak int21 entry 46 ; ENDLOG 47 ; 48 ; 24 Aug 87 The CARRY flag is now preserved for all DOS functions below 49 ; 038h Get/Set Country Code. 50 ; 04 Sep 87 Display the Interrupt Number and Registers when an illegal 51 ; software interrupt is executed by an application. This 52 ; is disabled by DBG OFF. 53 ; 09 Sep 87 DDIO interface changed to support a Double Word sector 54 ; number. 55 ; 05 Oct 87 Critical Error abort routine now uses the correct 56 ; terminate code. 57 ; 14 Oct 87 INT2F responds like a Network Redirector 58 ; 28 Oct 87 Preserve the state of the INDOS_INTERNAL flag during multiple 59 ; calls through DOS_ENTRY 60 ; 29 Oct 87 DS now points at the IBM PC ROS during an INT1B and INT1B 61 ; moved into IBMROS. 62 ; 7 Nov 87 Removal of development flags 63 ; 5 Jan 88 Terminate CP/M applications making DOS Calls in Concurrent DOS 64 ; 26 Feb 88 Terminate DOS applications making CP/M calls in DOSPLUS 65 ; 26 Apr 88 INT25/26 error codes only translated for Concurrent 66 ; 18 May 88 Prevent corruption of the EXIT_CODE by INT23 and INT24 67 ; when the application does not return. 68 ; 23 May 88 Prevent termination during CONFIG.SYS processing in DOSPLUS 69 ; 26 May 88 Force INDOS and ERROR flags to ZERO on terminate 70 ; 1 Jun 88 Modify INT28 to execute delays and work with SideKick. 71 ; 15 Jul 88 Support the IDLECNT field in the Process Descriptor and 72 ; CCB BUSY bit. 73 ; 07 Sep 88 PolyTron PolyWindows make DOS functions calls whenever 74 ; CS < SS. Therefore during the INT21 Entry and Exit code 75 ; interrupts must be disabled untill the stack swap occurs 76 ; even though the INDOS_FLAG is non-zero. 77 ; 24 Oct 88 File Lock/Unlock is now treated as an INACTIVE function. 78 ; 4 Nov 88 Correct the INT25/26 Error Translation Code 79 ; 21 Nov 88 Make INt25/26 Error Translation even better. 80 ; 29 Nov 88 Command Line Editor Insert on by default. 81 ; 21 Dec 88 IJs IDLE detection improvement only DELAY if someone else is 82 ; ready to run. 83 ; 11 Jan 89 Inc/Dec INTERNAL_FLAG to support DOS_ENTRY reentrancy. 84 ; 30 Jan 89 Inc/Dec INDOS_FLAG to INT25/26 Direct Disk I/O (CHKDSK/PRINT) 85 ; 19 Feb 89 Check the SHARE_FLAG for SHARING status in DR DOS 86 ; 9 Mar 89 Save/Restore PSP_USERSP/SS round int28's (SKPLUS/LINK/CTRL-C) 87 ; 18 Apr 89 ij Maintain the INDOS_FLAG correctly while processing INT 24 88 ; 18 Apr 89 Only take over INTs 5B and 5C for Debug Systems 89 ; 22 May 89 Setup DS before testing the state of the Share Flag. 90 ; 25 May 89 Support INT28_FLAG for functions 01 to 0C inclusive 91 ; 31 May 89 Move break_sp into DOS internal data area 92 ; 1 Jun 89 Save PSP_USERSS and SP during a critival Error (INT 24) 93 ; 05 Jun 89 Return NOT present for ASSIGN command and TRUE state for APPEND 94 ; 29 Jun 89 Save/restore retry_sp & retry_off around INT 24 95 ; 10 Jul 89 INT27 corrected to handle memory size of XXX1 (INFORM) 96 ; 31 Jul 89 Move stacks to DATA.PCM (CDROM support under way...) 97 ; 11 Aug 89 Create INT2F.PCM to support real INT 2F functions 98 ; 6 Sep 89 INT2A/84 keyboard busy loop added to do_int28 99 ; 23 Oct 89 MON_PERM removed from func5D/func5E/func5F (pain with MSNET..) 100 ; 9 Nov 89 Int 5B & 5C no longer taken over in DRDOS Debug versions 101 ; (Conflicts with PC-Net) 102 ; 15 Jan 90 pcmode_swapin/pcmode_swapout added for paged isr support 103 ; 25/Jan/90 Support Idle Data Area 104 ; 25/Jan/90 Add forth stack to support Japanese FEP and PTHOT. 105 ; 29/Jan/90 keep int21 CS/IP/FLAGS on local stack 106 ; 13/Feb/90 Added func63. 107 ; 20/Feb/90 CDOS checks caller is DOS process and aborts if not. 108 ; 22/Feb/90 Int25/26 checks disk label for passwords 109 ; Also swaps to normal stack like others DOS's 110 ; 7 Mar 90 Convert to register preserved function calls 111 ; 16 Mar 90 Int25/26 checks out for Leopard Beta 2 112 ; 4 Jun 90 Int21/25&35 don't swap stacks-ANSI.SYS Framework DOS window bug 113 ; 7 Jun 90 Print Rite fix moves to init.pcm 114 ; 29 Jun 90 CDOS idle detection uses timer info 115 ; 9 Aug 90 Int 8 tick count packed in P_CMOD 116 ; 19 Sep 90 load current_psp before checking PSP_PIDF (thanks Datapac) 117 ; 4 Oct 90 improved control break handling 118 ; 11 Oct 90 dev_map now supported to set LPTn/COMn mapping 119 ; 1 Nov 90 default Int 24 handler returns "Fail" 120 ; 19 feb 91 do_int28 calls read_time_and_date (BIOS CLOCK needs a call 121 ; every day) 122 ; 14 jun 91 copy user regs to local copy after int24 for pcshell 123 ; 8 aug 91 SI preserved on Int25/26 for SCAN 7.7 124 125 group PCMDATA PCMODE_DATA FDOS_DSEG 126 group PCMCODE PCM_CODE PCM_RODATA 127 128 [list -] 137 138 === Switch to base=000000h -> "PCM_CODE" 139 section PCM_CODE public align=1 class=CODE 140 ASSUME DS:PCMDATA 141 142 extrn pcmode_dseg:word 143 extrn break_check:near ; Control-C Check 144 extrn error_exit:near 145 extrn fdos_nocrit:near 146 extrn get_ddsc:near 147 148 ; 149 ; This entry point is used when a CALLF PSP:0005 has been executed 150 ; Here the function number is passed in CL and not AH and only 151 ; functions 0 to 24 inclusive can be executed. 152 ; 153 ; Entry Stack -> INT 21 Stack 154 ; 155 ; SP + 04 Return Offset Current Flags 156 ; SP + 02 PSP Segment PSP Segment 157 ; SP + 00 000Ah Return Offset 158 ; 159 Public call5_entry 160 call5_entry: 0 00003830 58 pop ax ; Remove 000Ah return Offset 0 00003831 9C pushf ; Save the Flags 0 00003832 55 push bp 0 00003833 89E5 mov bp,sp ; Get Stack Frame Pointer 0 00003835 8B4602 mov ax,[02 + bp] ; Get the FLAGS 0 00003838 874606 xchg ax,[06 + bp] ; Swap with the return offset 0 0000383B 894602 mov [02 + bp],ax ; and then save the return offset 0 0000383E 5D pop bp ; Restore the BP register 0 0000383F 88CC mov ah,cl ; Make it look like an INT 21 0 00003841 80FC24 cmp ah,024h ; Check for a valid function for this 0 00003844 760B jbe int21_entry ; entry technique if not return 172 illegal_iret: 0 00003846 B000 mov al,0 0 00003848 CF iret 175 176 int21_e01: 0 00003849 8E1EC600 mov ds,word ptr [INT31_SEGMENT] 0 0000384D EB1F jmp int21_e02 179 180 ; ++++++++++++++++++++++++++ 181 ; Int 20 - Program Terminate 182 ; ++++++++++++++++++++++++++ 183 ; 184 Public int20_entry 185 int20_entry: 0 0000384F B400 mov ah,00h 187 ; jmp int21_entry ; and jump to the standard entry point 188 189 ; +++++++++++++++++++++++++ 190 ; Int 21 - Function Request 191 ; +++++++++++++++++++++++++ 192 ; 193 Public int21_entry 194 int21_entry: 0 00003851 80FC74 cmp ah,pcmode_ftl ; is it in range ? 0 00003854 77F0 ja illegal_iret ; no, return BEFORE enabling ints 0 00003856 FC cld ; Clear the direction flag 0 00003857 061E55575652515350 PUSH_DOS ; Save User Registers 0 00003860 2E8E1E[0000] mov ds,[cs:pcmode_dseg] ; get CS relative Data Segment 0 00003865 2EF706[0000]FFFF test word [cs:pcmode_dseg],0FFFFh ; if Data Segment is zero then get 0 0000386C 74DB jz int21_e01 ; the Data segment address from 202 int21_e02: ; the segment portion of INT 31 203 204 ; 205 ; The following routines execute on the users stack without 206 ; modifing the INDOS_FLAG etc. These routines should only read 207 ; or update BASIC system variables. 208 ; 0 0000386E 80FC33 cmp ah,33h ; Func 33h - Control Break 0 00003871 740F je int21_e10 0 00003873 80FC50 cmp ah,50h ; Func 50h - Set PSP 0 00003876 7212 jb int21_e20 0 00003878 80FC51 cmp ah,51h ; Func 51h - Get PSP 0 0000387B 7605 jbe int21_e10 0 0000387D 80FC62 cmp ah,62h ; Func 62h - Get PSP 0 00003880 7508 jne int21_e20 217 int21_e10: 0 00003882 89E5 mov bp,sp ; Calculate the Stack Frame address 0 00003884 E8CA01 call internal_func ; "jump" to appropriate routine 0 00003887 E9AF00 jmp int21_exit 221 222 int21_e20: 0 0000388A FE06[0000] inc byte [indos_flag] ; Increment the INDOS Flag 224 0 0000388E A3[0000] mov [int21AX],ax ; save function number 226 0 00003891 803E[0000]26 cmp byte [WindowsHandleCheck],26h ; is windows active ? 0 00003896 7506 jne int21_e30 0 00003898 A1[0000] mov ax,[LocalMachineID] ; get local machine ID (zero unless 0 0000389B A3[0000] mov [machine_id],ax ; we are multi-tasking) 231 232 int21_e30: 0 0000389E A1[0000] mov ax,[current_psp] 0 000038A1 A3[0000] mov [owning_psp],ax 0 000038A4 8EC0 mov es,ax ; Get the PSP 236 0 000038A6 89E0 mov ax,sp 0 000038A8 26A32E00 mov [es:PSP_USERSP],ax ; Save the SS:SP pointer to 0 000038AC 268C163000 mov [es:PSP_USERSS],ss ; the register image ready for any 240 ; Critical errors that might occur 241 0 000038B1 8706[0000] xchg ax,[int21regs_off] ; point to callers registers 0 000038B5 A3[0000] mov [prev_int21regs_off],ax ; while saving current 0 000038B8 8CD0 mov ax,ss ; pointer to cater for 0 000038BA 8706[0000] xchg ax,[int21regs_seg] ; re-entrancy 0 000038BE A3[0000] mov [prev_int21regs_seg],ax 247 0 000038C1 31C0 xor ax,ax 0 000038C3 A3[0000] mov [remote_call],ax ; indicate we are a local call 0 000038C6 A2[0000] mov [int28_flag],al ; Do NOT Generate INT 28s 0 000038C9 A2[0000] mov [lfnpathflag], al 252 0 000038CC 8CD8 mov ax,ds 0 000038CE 8ED0 mov ss,ax ; swap initially to the error 0 000038D0 BC[0000] mov sp,offset error_stack ; stack until we know better 0 000038D3 A1[0000] mov ax,[int21AX] ; reload AX 257 0 000038D6 FB sti 0 000038D7 80FC59 cmp ah,59h ; Func 59h - Return Extended Error 0 000038DA 7433 je int21_e50 ; use the error stack 0 000038DC 80FC0C cmp ah,0Ch ; are we a character function 0 000038DF 7716 ja int21_e40 ; in range 01-0C ? 0 000038E1 80FC00 cmp ah,00h 0 000038E4 7411 je int21_e40 0 000038E6 803E[0000]00 cmp byte [error_flag],0 ; Use the "ERROR" Stack for the above 0 000038EB 7522 jnz int21_e50 ; functions 01-0C if error_flag set 0 000038ED BC[0000] mov sp,offset indos_stack ; else use the "INDOS" stack for these 0 000038F0 C606[0000]FF mov byte [int28_flag],TRUE & 0ffh ; functions and generate INT 28s 0 000038F5 EB18 jmp int21_e50 270 271 int21_e40: 0 000038F7 C606[0000]00 mov byte [error_flag],0 ; clear the error flag in case someone 273 ; hasn't returned from an Int 24 0 000038FC 50 push ax ; save function on stack 0 000038FD B482 mov ah,82h ; magic number in AH 0 000038FF CD2A int 2ah ; call server hook 0 00003901 58 pop ax ; recover function number 278 0 00003902 BC[0000] mov sp,offset normal_stack ; switch to the NORMAL stack 0 00003905 F606[0000]FF test byte [break_flag],0FFh ; is the Break Flag ON 0 0000390A 7403 jz int21_e50 ; NO - So continue 0 0000390C E8[0000] call break_check ; Handle the Control-C 283 int21_e50: 284 %if IDLE_DETECT 0 0000390F F706[0000]00C0 test word [idle_flags],word ptr IDLE_DISABLE ; don't break the pipeline unless 0 00003915 742C jz int21_idle ; IDLE checking enabled 287 int21_e60: 288 %endif 0 00003917 E81F01 call int21_func ; Execute the function 0 0000391A FA cli ; Stop anybody interfering 0 0000391B C42E[0000] les bp,[int21regs_ptr] ; point to user stack 0 0000391F 26884600 mov [es:reg_AL + bp],al ; always return AL 0 00003923 A1[0000] mov ax,[prev_int21regs_off] 0 00003926 A3[0000] mov [int21regs_off],ax 0 00003929 A1[0000] mov ax,[prev_int21regs_seg] 0 0000392C A3[0000] mov [int21regs_seg],ax 0 0000392F 8CC0 mov ax,es 0 00003931 8ED0 mov ss,ax ; back to users stack 0 00003933 89EC mov sp,bp 0 00003935 FE0E[0000] dec byte [indos_flag] ; Decrement the INDOS_FLAG 301 ; jmp int21_exit 302 303 Public int21_exit 304 int21_exit: 0 00003939 585B595A5E5F5D1F07 POP_DOS ; Restore Registers 0 00003942 CF iret 307 308 %if IDLE_DETECT 309 ; Only called if Idle detection is enabled 310 ; AH,DL as on Int 21 Entry 311 ; Decide if function is active/inactive 312 313 int21_idle: 314 ;---------- 315 %if IDLE_DETECT 0 00003943 8B1E[0000] mov bx,[int28_reload] ; reset the INT28 delay counter 0 00003947 891E[0000] mov [int28_delay],bx ; with the Reload value 318 %endif 0 0000394B 80FC5C cmp ah,5Ch 0 0000394E 7435 je int21_inactive ; Treat Lock/Unlock as inactive some 321 ; applications poll locked record. 0 00003950 80FC44 cmp ah,44h 0 00003953 7430 je int21_inactive ; IO Control Treated as Inactive 0 00003955 80FC2C cmp ah,2Ch 0 00003958 7720 ja int21_active ; > Get Current Time all active 0 0000395A 7429 je int21_inactive ; Get Current Time inactive 0 0000395C 80FC2A cmp ah,2Ah 0 0000395F 7424 je int21_inactive ; Get Current Date inactive 0 00003961 80FC0B cmp ah,0Bh 0 00003964 741F je int21_inactive ; Console Status 0 00003966 80FC0C cmp ah,0Ch 0 00003969 741A je int21_inactive ; Flush and Invoke Treated as Inactive 0 0000396B 80FC19 cmp ah,19h 0 0000396E 7415 je int21_inactive ; Get Current Disk 0 00003970 80FC06 cmp ah,06h 0 00003973 7505 jne int21_active ; Treat RAW_IO Status as Inactive 0 00003975 80FAFF cmp dl,0FFh 0 00003978 740B je int21_inactive 339 340 int21_active: ; Active function Executed 0 0000397A 830E[0000]02 or word [idle_flags],word ptr IDLE_DOSFUNC ; set DOSFUNC flag for BIOS 0 0000397F 90 nop ; identicalise 0 00003980 E82700 call active ; remember we were active 0 00003983 EB92 jmp int21_e60 ; continue execution 345 346 int21_inactive: 0 00003985 E80200 call inactive ; Process this INACTIVE function 0 00003988 EB8D jmp int21_e60 349 350 351 Public inactive 352 inactive: 0 0000398A 06 push es 0 0000398B 50 push ax 355 0 0000398C FF0E[0000] dec word [active_cnt] ; Decrement the count 0 00003990 7515 jnz inactive_10 ; Return if Non-Zero 358 0 00003992 A1[0000] mov ax,[idle_max] ; Get the default count value 0 00003995 A3[0000] mov [active_cnt],ax ; and reset the internal count 361 0 00003998 F706[0000]00C0 test word [idle_flags],IDLE_DISABLE ; Has Idle Checking been enabled 0 0000399E 7507 jnz inactive_10 ; Skip if NO. 0 000039A0 B80100 mov ax,PROC_IDLE ; Process is IDLE 0 000039A3 FF1E[0000] call far [idle_vec] ; Call the IDLE Handler 366 367 inactive_10: 0 000039A7 58 pop ax 0 000039A8 07 pop es 0 000039A9 C3 ret 371 ; 372 ; This routine will reset the active count for functions which 373 ; are treated as INACTIVE but which have active sub-functions. 374 ; 375 Public active 376 active: 0 000039AA 50 push ax 0 000039AB A1[0000] mov ax,[idle_max] ; Get the default count value 0 000039AE A3[0000] mov [active_cnt],ax ; and reset the internal count 0 000039B1 58 pop ax 0 000039B2 C3 ret 382 %endif 383 ; 384 ; 385 ; This function is invoked for functions number above the last 386 ; supported function number. It forces AL to zero and returns. 387 ; Just that and nothing more. 388 ; 389 ms_zero_AL: 0 000039B3 31C0 xor ax,ax ; AL = 0 for return 0 000039B5 C3 ret 392 393 ; DOS_ENTRY is used to call DOS functions internally. 394 ; eg. Func4B (exec) calls MS_X_OPEN, MS_X_READ, MS_X_CLOSE etc. 395 ; It is the responsibilty of the caller to make sure that no side 396 ; effects exist if this entry point is used. 397 ; eg. critical error handling 398 ; 399 ; 400 Public dos_entry 401 dos_entry: 0 000039B6 F8 clc 0 000039B7 FC cld 0 000039B8 9C pushf ; look like Int21 registers 0 000039B9 9C pushf 0 000039BA 9C pushf ; fake CS/IP positions 0 000039BB 1E push ds 0 000039BC 06 push es ; Save registers on the USER stack 0 000039BD 55 push bp ; no Stack Swap is executed and DS 0 000039BE 57 push di 0 000039BF 56 push si ; and ES are swapped. 0 000039C0 52 push dx 0 000039C1 51 push cx 0 000039C2 53 push bx 0 000039C3 50 push ax 0 000039C4 89E5 mov bp,sp ; Initialise Stack Frame 417 0 000039C6 E82502 call get_dseg ; Get our Data Area 419 0 000039C9 FE06[0000] inc byte [internal_flag] 421 0 000039CD FF36[0000] push word [fdos_data+0*2] ; save fdos pblk so we can 0 000039D1 FF36[0200] push word [fdos_data+1*2] ; be re-entrant(ish) 0 000039D5 FF36[0400] push word [fdos_data+2*2] 0 000039D9 FF36[0600] push word [fdos_data+3*2] 0 000039DD FF36[0800] push word [fdos_data+4*2] 0 000039E1 FF36[0A00] push word [fdos_data+5*2] 0 000039E5 FF36[0C00] push word [fdos_data+6*2] 429 0 000039E9 FF36[0000] push word [int21regs_off] 0 000039ED FF36[0000] push word [int21regs_seg] 432 0 000039F1 892E[0000] mov [int21regs_off],bp 0 000039F5 8C16[0000] mov [int21regs_seg],ss 435 0 000039F9 E85500 call internal_func ; Execute the function 0 000039FC 884600 mov [reg_AL + bp],al ; always return AL to caller 438 0 000039FF 8F06[0000] pop word [int21regs_seg] 0 00003A03 8F06[0000] pop word [int21regs_off] ; restore previous pointer user REGS 441 0 00003A07 8F06[0C00] pop word [fdos_data+6*2] 0 00003A0B 8F06[0A00] pop word [fdos_data+5*2] 0 00003A0F 8F06[0800] pop word [fdos_data+4*2] 0 00003A13 8F06[0600] pop word [fdos_data+3*2] 0 00003A17 8F06[0400] pop word [fdos_data+2*2] 0 00003A1B 8F06[0200] pop word [fdos_data+1*2] 0 00003A1F 8F06[0000] pop word [fdos_data+0*2] ; restore fdos_pb for nested calls 449 0 00003A23 FE0E[0000] dec byte [internal_flag] 451 0 00003A27 58 pop ax 0 00003A28 5B pop bx ; Update the registers then 0 00003A29 59 pop cx 0 00003A2A 5A pop dx ; set the flags and return 0 00003A2B 5E pop si 0 00003A2C 5F pop di ; to the user 0 00003A2D 5D pop bp 0 00003A2E 07 pop es 0 00003A2F 1F pop ds 0 00003A30 9D popf ; discard dos_IP 0 00003A31 9D popf ; and dos_CS 0 00003A32 9D popf ; get result 0 00003A33 7303 jnc dos_entry10 0 00003A35 F7D8 neg ax ; return using our negative error 0 00003A37 F9 stc ; conventions 467 dos_entry10: 0 00003A38 C3 ret 469 470 Public int21_func 471 472 int21_func: 473 ;---------- 474 ; On Entry: 475 ; AX, CX, DX, SI, DI as per Int 21 476 ; BX = ?? 477 ; BP = ?? 478 ; DS = pcmode data 479 ; ES = ?? 480 ; On Exit: 481 ; (to client function) 482 ; All general purpose registers as per Int 21 entry 483 ; ES = dos_DS 484 ; 485 0 00003A39 31DB xor bx,bx ; BH = 0 0 00003A3B 88E3 mov bl,ah ; BX = function number 0 00003A3D D1E3 shl bx,1 ; make it a word offset 0 00003A3F 2EFFB7[0000] push word [cs:pcmode_ft + bx] ; save address of Function 0 00003A44 C42E[0000] les bp,[int21regs_ptr] 0 00003A48 268B5E02 mov bx,[es:reg_BX + bp] ; reload from dos_BX,dos_BP,and dos_DS 0 00003A4C 26C46E0C les bp,[es:reg_BP + bp] 0 00003A50 C3 ret 494 495 496 internal_func: 497 ;------------- 498 ; On Entry: 499 ; All registers as per Int 21 EXCEPT 500 ; DS = pcmode data 501 ; BP = dos_REGS stack frame 502 ; On Exit: 503 ; (to client function) 504 ; ES = dos_DS 505 ; 0 00003A51 88E0 mov al,ah ; function number in AL 0 00003A53 98 cbw ; AH = 0 0 00003A54 93 xchg ax,bx ; get subfunction in BX 0 00003A55 D1E3 shl bx,1 ; make offset in the internal table 0 00003A57 2EFFB7[0000] push word [cs:pcmode_ft + bx] ; save address of Function 0 00003A5C 93 xchg ax,bx ; restore BX 0 00003A5D 8B4600 mov ax,[reg_AX + bp] ; recover function number 0 00003A60 8E460E mov es,[reg_DS + bp] ; ES = callers DS 0 00003A63 C3 ret ; "jump" to handler 515 516 ; INT25 and INT26 direct disk I/O interface 517 ; 518 ;Standard DOS 1.xx - 3.30 INT25/26 Interface 519 ;=========================================== 520 ; 521 ; entry: al = drive number 522 ; ds = DMA segment 523 ; bx = DMA offset 524 ; cx = number of sectors 525 ; dx = beginning relative sector 526 ; 527 ; 528 ;Enhanced DOS 3.31 INT25/26 Interface 529 ;==================================== 530 ; 531 ; If CX == 0FFFFh then the application is using the enhanced 532 ; INT25/INT26 interface which allows access to more than 64K 533 ; sectors. 534 ; 535 ; entry: al = drive number 536 ; bx = Parameter block Offset 537 ; ds = Parameter block Segment 538 ; 539 ; Parameter Block Format 540 ;DS:BX -> DD Starting Sector No. 541 ; DW Number of Sectors 542 ; DD Transfer Address 543 ; 544 ; 545 ; exit: C flag = 0 if successful 546 ; = 1 if unsuccessful 547 ; ax = error code(if CF = 1) 548 ; ah physical error 549 ; al logical error 550 ; Users orginal flags left on stack 551 ; 552 ; 553 DDIO_INT13 equ 0 554 DDIO_READ_OP equ 1 555 DDIO_WRITE_OP equ 2 556 557 ; ++++++++++++++++++++++++++++ 558 ; Int 26 - Absolute Disk Write 559 ; ++++++++++++++++++++++++++++ 560 ; 561 Public int26_entry 562 int26_entry: 0 00003A64 B402 mov ah,DDIO_WRITE_OP ; This is a WRITE operation 0 00003A66 EB02 jmp int26_10 565 566 567 ; +++++++++++++++++++++++++++ 568 ; Int 25 - Absolute Disk Read 569 ; +++++++++++++++++++++++++++ 570 ; 571 Public int25_entry 572 int25_entry: 0 00003A68 B401 mov ah,DDIO_READ_OP ; This is a READ operation 574 int26_10: ; Common Direct Disk I/O code 0 00003A6A FC cld 0 00003A6B 1E push ds 0 00003A6C 06 push es 0 00003A6D 57 push di 0 00003A6E 52 push dx ; save DX for FLASHCARD 0 00003A6F 1E push ds 0 00003A70 07 pop es ; ES = callers DS 0 00003A71 E87A01 call get_dseg ; Get PCMODE Data Segment 0 00003A74 FE06[0000] inc byte [indos_flag] ; Update the INDOS_FLAG 0 00003A78 8C16[0200] mov [normal_stack+2],ss ; save users SS:SP 0 00003A7C 8926[0000] mov [normal_stack],sp 0 00003A80 FA cli 0 00003A81 1E push ds 0 00003A82 17 pop ss ; use normal stack when in here 0 00003A83 BC[0000] mov sp,offset normal_stack 0 00003A86 FB sti 0 00003A87 41 inc cx ; CX = FFFF indicates this is 0 00003A88 742D jz int26_30 593 ; CHECK FOR PARITIONS > 32 MBytes... 0 00003A8A 49 dec cx ; CX restored 0 00003A8B 06 push es 0 00003A8C 50 push ax 0 00003A8D 53 push bx 0 00003A8E 52 push dx 0 00003A8F E8[0000] call get_ddsc ; ES:BX -> DDSC_ 0 00003A92 BF0102 mov di,0201h ; assume bad drive 0 00003A95 7217 jc int26_20 0 00003A97 BF0702 mov di,0207h ; assume large media, and this error 603 %if 0 604 ; This code works out the total number of sectors on a drive 605 mov ax,[es:DDSC_NCLSTRS + bx] ; get last cluster # 606 dec ax ; make it # data clusters 607 xor dx,dx 608 mov dl,[es:DDSC_CLMSK + bx] ; get sec/cluster -1 609 inc dx ; DX = sec/cluster 610 mul dx ; DX:AX = # data sectors 611 add ax,[es:DDSC_DATADDR + bx] ; add in address of 1st data sector 612 adc dx,0 613 %else 0 00003A9A 268B470D mov ax,[es:DDSC_NCLSTRS + bx] ; get last cluster # 0 00003A9E 31D2 xor dx,dx 0 00003AA0 268A5704 mov dl,[es:DDSC_CLMSK + bx] ; get sec/cluster -1 0 00003AA4 42 inc dx ; DX = sec/cluster 0 00003AA5 F7E2 mul dx ; DX:AX is vaguely the # sectors 0 00003AA7 85D2 test dx,dx ; close enough for bill 620 %endif 0 00003AA9 F9 stc ; assume an error 0 00003AAA 7502 jnz int26_20 0 00003AAC 31FF xor di,di ; DI = zero, no error 624 int26_20: 0 00003AAE 5A pop dx 0 00003AAF 5B pop bx 0 00003AB0 58 pop ax 0 00003AB1 07 pop es 0 00003AB2 7312 jnc int26_40 0 00003AB4 97 xchg ax,di ; AX = error code 0 00003AB5 EB44 jmp int26_60 ; return it 632 int26_30: 0 00003AB7 268B17 mov dx,word ptr [es:0 + bx] ; Get Starting Sector Low 0 00003ABA 268B7F02 mov di,word ptr [es:2 + bx] ; Get Starting Sector High 0 00003ABE 268B4F04 mov cx,word ptr [es:4 + bx] ; Get No. of sectors to transfer 0 00003AC2 26C45F06 les bx,[es:6 + bx] ; Tranfer Address Offset 637 int26_40: 0 00003AC6 A3[0200] mov [FD_DDIO_DRV_OP],ax ; save drive and operation 0 00003AC9 890E[0400] mov [FD_DDIO_NSECTORS],cx ; No. of Sectors 0 00003ACD 8916[0600] mov [FD_DDIO_STARTLOW],dx ; Starting Sector No. 0 00003AD1 893E[0800] mov [FD_DDIO_STARTHIGH],di ; High Word of Sector Number 0 00003AD5 891E[0A00] mov [FD_DDIO_DMAOFF],bx ; DMA Offset 0 00003AD9 8C06[0C00] mov [FD_DDIO_DMASEG],es ; DMA Segment 644 0 00003ADD C706[0000]5400 mov word [FD_FUNC],FD_DDIO 0 00003AE3 E8[0000] call fdos_nocrit ; let the FDOS do the work 0 00003AE6 F7D8 neg ax ; AX is DOS extended error 0 00003AE8 7412 jz int26_exit 0 00003AEA 2C13 sub al,-ED_PROTECT ; get AL to Int24 error format 0 00003AEC 3C0C cmp al,-(ED_GENFAIL-ED_PROTECT) 0 00003AEE 7602 jbe int26_50 0 00003AF0 B00C mov al,-(ED_GENFAIL-ED_PROTECT) 653 int26_50: ; no, make it general failure 0 00003AF2 88C4 mov ah,al ; save error in AH 0 00003AF4 BB[E002] mov bx,offset int13_error 0 00003AF7 2ED7 cs xlatb ; convert error to int13 format 0 00003AF9 86C4 xchg al,ah ; get errors in correct registers 658 int26_60: 0 00003AFB F9 stc ; Set the Carry Flag when an error 660 int26_exit: ; Occurs and return to the calling app. 0 00003AFC FA cli 0 00003AFD 8E16[0200] mov ss,[normal_stack+2] ; back to user stack 0 00003B01 8B26[0000] mov sp,[normal_stack] 0 00003B05 FB sti 0 00003B06 FE0E[0000] dec byte [indos_flag] ; Update the INDOS_FLAG 0 00003B0A FB sti 0 00003B0B 5A pop dx 0 00003B0C 5F pop di 0 00003B0D 07 pop es 0 00003B0E 1F pop ds ; restore callers registers 0 00003B0F CB retf ; leave flags on stack 672 0 00003B10 030280011002400204 int13_error db 03h,02h,80h,01h,10h,02h,40h,02h,04h,02h,02h,02h,02h 0 00003B19 02020202 674 675 ; ++++++++++++++++++++++++++++++++++++ 676 ; Int 27 - Terminate but Stay Resident 677 ; ++++++++++++++++++++++++++++++++++++ 678 ; 679 Public int27_entry 680 int27_entry: 0 00003B1D B80031 mov ax,3100h ; Convert this to a DOS 'Terminate and 0 00003B20 83C20F add dx,15 ; Stay Resident' function by converting the 0 00003B23 D1DA rcr dx,1 ; memory size in bytes to paragraphs. 0 00003B25 D1EA shr dx,1 ; On entry DX == memsize + 1 bytes therefore 0 00003B27 D1EA shr dx,1 ; round upto a paragraph boundary by adding 0 00003B29 D1EA shr dx,1 ; 15 then divide by 16 0 00003B2B E923FD jmp int21_entry 688 689 ; 690 ; DO_INT24: 691 ; On Entry:- 692 ; AH Set for INT 24 693 ; AL Drive Number (0 = A:) 694 ; DI Error Code 695 ; ES:SI Device Header Control Block 696 ; 697 ; On Exit:- 698 ; AL Error Response Retry/Ignore/Fail 699 ; 700 ; INT 24 Critical Error:- 701 ; On Entry:- AH/7 0 = Disk Device 702 ; AH/5 0 = IGNORE is an Invalid Response 703 ; AH/4 0 = RETRY in an Invalid Response 704 ; AH/3 0 = FAIL is an Invalid Response 705 ; AH/2-1 00= DOS Area 706 ; 01= File Allocation Table 707 ; 10= Directory 708 ; 11= Data 709 ; AH/0 0 = Read, 1 = Write 710 ; 711 ; AL 1 Retry the Operation 712 ; BP:SI Device Header Control Block 713 ; DI High Byte Undefined, Low Byte Error Code 714 ; 715 ; On Exit:- AL 0 = IGNORE Error 716 ; 1 = RETRY the Operation 717 ; 2 = TERMINATE using INT 23 718 ; 3 = FAIL the current DOS function 719 ; 720 Public do_int24 721 do_int24: 0 00003B2E 803E[0000]00 cmp byte [error_flag],0 ; Skip the critical error routine 0 00003B33 7403 jz di24_05 ; if the handler is active 0 00003B35 B003 mov al,ERR_FAIL ; Then return the FAIL condition 0 00003B37 C3 ret ; to the calling routine 726 di24_05: 0 00003B38 50 push ax 0 00003B39 55 push bp ; Save our Base Pointer and then the 0 00003B3A FA cli ; Disable Interupts 730 0 00003B3B 8CC5 mov bp,es ; BP:SI points to dev header 0 00003B3D 8E06[0000] mov es,[current_psp] ; Get the current PSP and USER Stack 733 0 00003B41 26FF363000 push word [es:PSP_USERSS] ; Save the Users Real SS and SP 0 00003B46 26FF362E00 push word [es:PSP_USERSP] ; on the internal Stack 0 00003B4B FF36[0000] push word [retry_sp] ; also the retry info 0 00003B4F FF36[0000] push word [retry_off] 0 00003B53 FF36[0000] push word [remote_call] 0 00003B57 FF36[0000] push word [machine_id] 740 0 00003B5B 8926[0000] mov [critical_sp],sp ; Internal Stack Pointer Offset 742 0 00003B5F FE06[0000] inc byte [error_flag] ; Entering Critical Error Handler 0 00003B63 FE0E[0000] dec byte [indos_flag] ; I may be gone some time.... 745 ; (an application error handler need 746 ; never return so tidy up first) 747 0 00003B67 268E163000 mov ss,[es:PSP_USERSS] ; Switch to the Users Stack 0 00003B6C 268B262E00 mov sp,[es:PSP_USERSP] 750 0 00003B71 CD24 int 24h ; Call the Critical Error Handler 752 0 00003B73 FC cld 0 00003B74 FA cli ; paranioa..... 0 00003B75 E87600 call get_dseg ; Reload DS just in case someone at 756 ; A-T or Lotus cannot read 757 0 00003B78 1E push ds 0 00003B79 17 pop ss ; Swap back to the Internal stack 0 00003B7A 8B26[0000] mov sp,[critical_sp] ; and process the returned info. 761 0 00003B7E 8F06[0000] pop word [machine_id] 0 00003B82 8F06[0000] pop word [remote_call] 0 00003B86 8F06[0000] pop word [retry_off] ; restore retry info 0 00003B8A 8F06[0000] pop word [retry_sp] 0 00003B8E 8E06[0000] mov es,[current_psp] ; Restore the Users original SS and 0 00003B92 268F062E00 pop word [es:PSP_USERSP] ; SP registers from the Stack 0 00003B97 268F063000 pop word [es:PSP_USERSS] 769 0 00003B9C 5D pop bp 0 00003B9D 5B pop bx ; Restore BP and original AX 0 00003B9E FB sti 773 0 00003B9F C606[0000]00 mov byte [error_flag],0 0 00003BA4 FE06[0000] inc byte [indos_flag] 776 0 00003BA8 3C00 cmp al,ERR_IGNORE 0 00003BAA 7507 jnz di24_10 ; Check for IGNORE and force 0 00003BAC F6C720 test bh,OK_IGNORE 0 00003BAF 7502 jnz di24_10 ; to become a FAIL if its an 0 00003BB1 B003 mov al,ERR_FAIL ; invalid response. 782 783 di24_10: 0 00003BB3 3C01 cmp al,ERR_RETRY 0 00003BB5 7507 jnz di24_20 ; Check for RETRY and force 0 00003BB7 F6C710 test bh,OK_RETRY 0 00003BBA 7502 jnz di24_20 ; to become a FAIL if its an 0 00003BBC B003 mov al,ERR_FAIL ; invalid response. 789 790 di24_20: 0 00003BBE 3C03 cmp al,ERR_FAIL 0 00003BC0 7507 jnz di24_30 ; Check for FAIL and force 0 00003BC2 F6C708 test bh,OK_FAIL 0 00003BC5 7502 jnz di24_30 ; to become a ABORT if its an 0 00003BC7 B002 mov al,ERR_ABORT ; invalid response. 796 797 di24_30: 0 00003BC9 3C02 cmp al,ERR_ABORT ; Do not return if the ABORT option 0 00003BCB 7405 jz di24_abort ; has been selected but execute 800 ; INT 23 directly 0 00003BCD 3C03 cmp al,ERR_FAIL ; All invalid reponses are converted 0 00003BCF 7701 ja di24_abort ; to ABORT 803 di24_40: 0 00003BD1 C3 ret 805 806 di24_abort: ; Abort this Process 0 00003BD2 A1[0000] mov ax,[current_psp] ; check not root application because 0 00003BD5 8EC0 mov es,ax ; it must not be terminated so force 0 00003BD7 263B061600 cmp ax,[es:PSP_PARENT] ; Is this the root Process 0 00003BDC B003 mov al,ERR_FAIL ; convert the error to FAIL 0 00003BDE 74F1 je di24_40 ; if not we terminate 0 00003BE0 C606[0000]02 mov byte [exit_type],TERM_ERROR ; Set the correct exit Type 0 00003BE5 B8004C mov ax,04C00h ; and return code. 0 00003BE8 A3[0000] mov [int21AX],ax 0 00003BEB E9[0000] jmp func4C ; Then terminate 816 817 ; 818 ; Get the PCMODE Emulator data Segment from the PD 819 ; 820 Public get_dseg 821 get_dseg: 0 00003BEE 2E8E1E[0000] mov ds,[cs:pcmode_dseg] ; get CS relative Data Segment 0 00003BF3 2EF706[0000]FFFF test word [cs:pcmode_dseg],0FFFFh ; If Data Segment is zero then get 0 00003BFA 7401 jz get_d10 ; the Data segment address from 0 00003BFC C3 ret ; the segment portion of INT 31 826 get_d10: 0 00003BFD 8E1EC600 mov ds,word ptr [INT31_SEGMENT] 0 00003C01 C3 ret 829 830 831 ; 832 ;INVALID_FUNCTION is called when any unsupported function has been executed 833 ; 834 Public invalid_function 835 invalid_function: 0 00003C02 B8FFFF mov ax,ED_FUNCTION ; Mark as Invalid Function 0 00003C05 E9[0000] jmp error_exit ; and Exit 838 839 840 Public reload_registers 841 reload_registers: 842 ;---------------- 843 ; This routine is called to reload the registers we expect to have correct 844 ; at the start of a PCMODE function. 0 00003C08 1E push ds 0 00003C09 C52E[0000] lds bp,[int21regs_ptr] 0 00003C0D 3E8B4600 mov ax,[ds:reg_AX + bp] 0 00003C11 3E8B5E02 mov bx,[ds:reg_BX + bp] 0 00003C15 3E8B4E04 mov cx,[ds:reg_CX + bp] 0 00003C19 3E8B5606 mov dx,[ds:reg_DX + bp] 0 00003C1D 3E8B7608 mov si,[ds:reg_SI + bp] 0 00003C21 3E8B7E0A mov di,[ds:reg_DI + bp] 0 00003C25 3EC46E0C les bp,[ds:reg_BP + bp] 0 00003C29 1F pop ds 0 00003C2A C3 ret 856 857 PCM_CODE ends 858 === Switch to base=00C180h -> "PCMODE_DATA" 859 section PCMODE_DATA public align=2 class=DATA 860 extrn retry_sp:word 861 extrn retry_off:word 862 extrn break_flag:byte 863 extrn current_psp:word 864 extrn current_dsk:byte 865 extrn dma_offset:word 866 extrn dma_segment:word 867 extrn error_flag:byte 868 extrn error_stack:word 869 extrn exit_type:byte 870 extrn int21regs_ptr:dword 871 extrn int21regs_off:word 872 extrn int21regs_seg:word 873 extrn prev_int21regs_ptr:dword 874 extrn prev_int21regs_off:word 875 extrn prev_int21regs_seg:word 876 extrn indos_flag:byte 877 extrn indos_stack:word 878 extrn LocalMachineID:word 879 extrn machine_id:word 880 extrn int21AX:word 881 extrn normal_stack:word 882 extrn owning_psp:word 883 extrn remote_call:word 884 extrn WindowsHandleCheck:byte 885 extrn lfnpathflag:byte 886 887 %if IDLE_DETECT 888 extrn active_cnt:word 889 extrn idle_max:word 890 extrn idle_flags:word 891 extrn idle_vec:dword 892 extrn int28_delay:word 893 extrn int28_reload:word 894 %endif 895 896 extrn critical_sp:word 897 extrn internal_flag:byte 898 extrn int28_flag:byte 899 PCMODE_DATA ends 900 === Switch to base=000000h -> "PCM_CODE" 901 section PCM_CODE public align=1 class=CODE 901 ****************** warning: segment attributes specified on redeclaration of segment: ignoring [-w+other] 902 extrn func00:near, func01:near, func02:near, func03:near 903 extrn func04:near, func05:near, func06:near, func07:near 904 extrn func08:near, func09:near, func0A:near, func0B:near 905 extrn func0C:near, func0D:near, func0E:near, func0F:near 906 extrn func10:near, func11:near, func12:near, func13:near 907 extrn func14:near, func15:near, func16:near, func17:near 908 extrn func19:near, func1A:near, func1B:near, func1C:near 909 extrn func1F:near, func21:near, func22:near, func23:near 910 extrn func24:near, func25:near, func26:near, func27:near 911 extrn func28:near, func29:near, func2A:near, func2B:near 912 extrn func2C:near, func2D:near, func2E:near, func2F:near 913 extrn func30:near, func31:near, func32:near, func33:near 914 extrn func34:near, func35:near, func36:near, func37:near 915 extrn func38:near, func39:near, func3A:near, func3B:near 916 extrn func3C:near, func3D:near, func3E:near, func3F:near 917 extrn func40:near, func41:near, func42:near, func43:near 918 extrn func44:near, func45:near, func46:near, func47:near 919 extrn func48:near, func49:near, func4A:near, func4B:near 920 extrn func4C:near, func4D:near, func4E:near, func4F:near 921 extrn func50:near, func51:near, func52:near, func53:near 922 extrn func54:near, func55:near, func56:near, func57:near 923 extrn func58:near, func59:near, func5A:near, func5B:near 924 extrn func5C:near, func5D:near, func5E:near, func5F:near 925 extrn func60:near, func62:near, func63:near, func65:near 926 extrn func66:near, func67:near, func68:near, func69:near 927 extrn func6C:near, func71:near, func73:near 928 PCM_CODE ends 929 930 ; 931 ; The following Function tables are forced onto a word boundary 932 ; because of the word alignment of the PCMODE_RODATE segment. 933 ; Only word based Read Only data is held in this segment. 934 ; 935 === Switch to base=000000h -> "PCM_RODATA" 936 section PCM_RODATA public align=2 class=CODE 937 Public pcmode_ft, pcmode_ftl 938 pcmode_ft label word 0 0000B868 [0000] dw func00 ; (00) Terminate Program 0 0000B86A [0000] dw func01 ; (01) Read Keyboard and Echo 0 0000B86C [0000] dw func02 ; (02) Display Character 0 0000B86E [0000] dw func03 ; (03) Auxilary Input 0 0000B870 [0000] dw func04 ; (04) Auxilary Output 0 0000B872 [0000] dw func05 ; (05) Print Character 0 0000B874 [0000] dw func06 ; (06) Direct Console I/O 0 0000B876 [0000] dw func07 ; (07) Direct Console Input 0 0000B878 [0000] dw func08 ; (08) Read Keyboard 0 0000B87A [0000] dw func09 ; (09) Display String 0 0000B87C [0000] dw func0A ; (0A) Buffered Keyboard Input 0 0000B87E [0000] dw func0B ; (0B) Check Keyboard Status 0 0000B880 [0000] dw func0C ; (0C) Flush Buffer, Read Keyboard 0 0000B882 [0000] dw func0D ; (0D) Reset Disk 0 0000B884 [0000] dw func0E ; (0E) Select Disk 0 0000B886 [0000] dw func0F ; (0F) Open File 0 0000B888 [0000] dw func10 ; (10) Close File 0 0000B88A [0000] dw func11 ; (11) Search for First 0 0000B88C [0000] dw func12 ; (12) Search for Next 0 0000B88E [0000] dw func13 ; (13) Delete File 0 0000B890 [0000] dw func14 ; (14) Sequential Read 0 0000B892 [0000] dw func15 ; (15) Sequential Write 0 0000B894 [0000] dw func16 ; (16) Create File 0 0000B896 [0000] dw func17 ; (17) Rename File 0 0000B898 [8301] dw ms_zero_AL ; (18) Unused DOS function (AL = 0) 0 0000B89A [0000] dw func19 ; (19) Current Disk 0 0000B89C [0000] dw func1A ; (1A) Set Disk Transfer Address 0 0000B89E [0000] dw func1B ; (1B) *Get Default Drive Data 0 0000B8A0 [0000] dw func1C ; (1C) *Get Drive Data 0 0000B8A2 [8301] dw ms_zero_AL ; (1D) Unused DOS function (AL = 0) 0 0000B8A4 [8301] dw ms_zero_AL ; (1E) Unused DOS function (AL = 0) 0 0000B8A6 [0000] dw func1F ; (1F) Get Default DPB 0 0000B8A8 [8301] dw ms_zero_AL ; (20) Unused DOS function (AL = 0) 0 0000B8AA [0000] dw func21 ; (21) Random Read 0 0000B8AC [0000] dw func22 ; (22) Random Write 0 0000B8AE [0000] dw func23 ; (23) File Size 0 0000B8B0 [0000] dw func24 ; (24) Set Relative Record 0 0000B8B2 [0000] dw func25 ; (25) Set Interrupt Vector 0 0000B8B4 [0000] dw func26 ; (26) Duplicate PSP 0 0000B8B6 [0000] dw func27 ; (27) Random Block Read 0 0000B8B8 [0000] dw func28 ; (28) Random Block Write 0 0000B8BA [0000] dw func29 ; (29) Parse File Name 0 0000B8BC [0000] dw func2A ; (2A) Get Date 0 0000B8BE [0000] dw func2B ; (2B) Set Date 0 0000B8C0 [0000] dw func2C ; (2C) Get Time 0 0000B8C2 [0000] dw func2D ; (2D) Set Time 0 0000B8C4 [0000] dw func2E ; (2E) Set/Reset Verify Flag 0 0000B8C6 [0000] dw func2F ; (2F) Get Disk Transfer Address 0 0000B8C8 [0000] dw func30 ; (30) Get Version Number 0 0000B8CA [0000] dw func31 ; (31) Keep Process 0 0000B8CC [0000] dw func32 ; (32) Get DPB 0 0000B8CE [0000] dw func33 ; (33) CONTROL-C Check 0 0000B8D0 [0000] dw func34 ; (34) Get the Indos Flag 0 0000B8D2 [0000] dw func35 ; (35) Get Interrupt Vector 0 0000B8D4 [0000] dw func36 ; (36) Get Disk Free Space 0 0000B8D6 [0000] dw func37 ; (37) Get/Set Switch Character 0 0000B8D8 [0000] dw func38 ; (38) Return Country Dependant Info 0 0000B8DA [0000] dw func39 ; (39) Create Sub-directory 0 0000B8DC [0000] dw func3A ; (3A) Remove Sub-directory 0 0000B8DE [0000] dw func3B ; (3B) Change Sub-directory 0 0000B8E0 [0000] dw func3C ; (3C) Create a File 0 0000B8E2 [0000] dw func3D ; (3D) Open a File Handle 0 0000B8E4 [0000] dw func3E ; (3E) Close a File Handle 0 0000B8E6 [0000] dw func3F ; (3F) Read from a File/Device 0 0000B8E8 [0000] dw func40 ; (40) Write to a File/Device 0 0000B8EA [0000] dw func41 ; (41) Delete a Directory Entry 0 0000B8EC [0000] dw func42 ; (42) Move a File Pointer 0 0000B8EE [0000] dw func43 ; (43) Change Attributes 0 0000B8F0 [0000] dw func44 ; (44) I/O Control 0 0000B8F2 [0000] dw func45 ; (45) Duplicate File Handle 0 0000B8F4 [0000] dw func46 ; (46) Force a Duplicate File Handle 0 0000B8F6 [0000] dw func47 ; (47) Return Text of Current Directory 0 0000B8F8 [0000] dw func48 ; (48) Allocate Memory 0 0000B8FA [0000] dw func49 ; (49) Free Allocated Memory 0 0000B8FC [0000] dw func4A ; (4A) Modify Allocated Memory 0 0000B8FE [0000] dw func4B ; (4B) Load and Execute Program 0 0000B900 [0000] dw func4C ; (4C) Terminate a Process 0 0000B902 [0000] dw func4D ; (4D) Get Return Code 0 0000B904 [0000] dw func4E ; (4E) Find Matching File 0 0000B906 [0000] dw func4F ; (4F) Find Next Matching File 0 0000B908 [0000] dw func50 ; (50) Set Current PSP 0 0000B90A [0000] dw func51 ; (51) Get Current PSP 0 0000B90C [0000] dw func52 ; (52) *Get In Vars 0 0000B90E [0000] dw func53 ; (53) *Build DPB from BPB 0 0000B910 [0000] dw func54 ; (54) Return Verify State 0 0000B912 [0000] dw func55 ; (55) Create a New PSP 0 0000B914 [0000] dw func56 ; (56) Move a Directory Entry 0 0000B916 [0000] dw func57 ; (57) Get/Set File Date and Time 0 0000B918 [0000] dw func58 ; (58) Memory Allocation Strategy 0 0000B91A [0000] dw func59 ; (59) Get Extended Error 0 0000B91C [0000] dw func5A ; (5A) Create Temporary File 0 0000B91E [0000] dw func5B ; (5B) Create New File 0 0000B920 [0000] dw func5C ; (5C) File Lock Control 0 0000B922 [0000] dw func5D ; (5D) Internal DOS Function 0 0000B924 [0000] dw func5E ; (5E) Control Local Machine Data 0 0000B926 [0000] dw func5F ; (5F) Get Network Assignments 0 0000B928 [0000] dw func60 ; (60) Perform Name Processing 0 0000B92A [8301] dw ms_zero_AL ; (61) ?? Parse Path (AL = 0) 0 0000B92C [0000] dw func62 ; (62) Get Current PSP 0 0000B92E [0000] dw func63 ; (63) Get Lead Byte Table 0 0000B930 [D203] dw invalid_function ; (64) *Saves AL and Returns 0 0000B932 [0000] dw func65 ; (65) Get Extended Country Information 0 0000B934 [0000] dw func66 ; (66) Get/Set Global Code Page 0 0000B936 [0000] dw func67 ; (67) Set Handle Count 0 0000B938 [0000] dw func68 ; (68) Commit File 0 0000B93A [0000] dw func69 ; (69) Get Serial number 0 0000B93C [0000] dw func68 ; (6A) Commit File (again) 0 0000B93E [D203] dw invalid_function ; (6B) Unknown DOS 4 0 0000B940 [0000] dw func6C ; (6C) Extended Open/Create 0 0000B942 [8301] dw ms_zero_AL ; (6D) Unused DOS function (AL = 0) 0 0000B944 [8301] dw ms_zero_AL ; (6E) Unused DOS function (AL = 0) 0 0000B946 [8301] dw ms_zero_AL ; (6F) Unused DOS function (AL = 0) 0 0000B948 [8301] dw ms_zero_AL ; (70) Unused DOS function (AL = 0) 0 0000B94A [0000] dw func71 ; (71) LFN and 64-bit file functions 0 0000B94C [8301] dw ms_zero_AL ; (72) Unused DOS function (AL = 0) 0 0000B94E [0000] dw func73 ; (73) DOS 7 FAT32 functions 1055 pcmode_ftl equ (offset $ - offset pcmode_ft)/2 1056 ;************************** 1057 ;* Do Not Move This Entry * 1058 ;************************** 0 0000B950 [8301] dw ms_zero_AL ; Illegal Function Handler 1060 1061 PCM_RODATA ends 1062 1063 end === Trace listing source: drdos/bin/cio.lst 1 ; File : $CIO.ASM$ 2 ; 3 ; Description : 4 ; 5 ; Original Author : DIGITAL RESEARCH 6 ; 7 ; Last Edited By : $CALDERA$ 8 ; 9 ;-----------------------------------------------------------------------; 10 ; Copyright Work of Caldera, Inc. All Rights Reserved. 11 ; 12 ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, 13 ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. 14 ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES 15 ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF 16 ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO 17 ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE 18 ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE 19 ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, 20 ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, 21 ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, 22 ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF 23 ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT 24 ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND 25 ; CIVIL LIABILITY. 26 ;-----------------------------------------------------------------------; 27 ; 28 ; *** Current Edit History *** 29 ; *** End of Current Edit History *** 30 ; $Log: $ 31 ; CIO.A86 1.20 94/12/01 10:05:21 32 ; Made cooked_write and is_device aware of FCB writes; 33 ; CIO.A86 1.19 94/06/28 12:21:07 34 ; Fix last_key_ext bug 35 ; CIO.A86 1.18 94/05/12 14:06:22 36 ; The routine cooked_status now sets a flag last_key_ext if the keycode is 0. 37 ; On entry, it checks this flag to see if the last one was 0, and if so does 38 ; not do the checks for the control keys. In this way, Alt-R and Alt-Q can 39 ; be distinguished from Ctrl-S and Ctrl-P. 40 ; CIO.A86 1.17 93/12/21 17:58:15 41 ; Preserve BX round clock read 42 ; Update char_error so DS:SI -> device driver header itself 43 ; CIO.A86 1.10 93/05/06 19:28:03 44 ; Move int 23/28 support to CIO. 45 ; Read the clock in idle_dev, not int 28 loop. 46 ; CIO.A86 1.9 93/05/05 23:30:44 47 ; int 2A/84 is now only generated on input-and-wait functions 48 ; CIO.A86 1.8 93/03/25 15:05:56 49 ; tweak console block output 50 ; ENDLOG 51 ; 52 ; This module contains all the Character I/O functions used by PCMODE 53 ; 54 ; 12 Nov 87 Disable Control-Break when the Console Output mode is RAW 55 ; 24 Feb 88 Display Control characters correctly. ie "^X" 56 ; 23 May 88 Support ^S to Pause screen output. 57 ; 25 May 88 Support Control-P for Cooked_Write and remove Kanji Character 58 ; check. 59 ; 26 May 88 Check for CTLC on CON_DEV when character input is redirected. 60 ; Correctly detect EOF on redirected input. 61 ; 17 Aug 88 Call PRN device with Open/Close on ^P 62 ; 30 Aug 88 Jump to correct exit when Open/Close is not supported by a 63 ; device driver for ^P. 64 ; 14 Sep 88 Break checking should only be carried out when the INDOS_FLAG 65 ; is 1. (Novell and Cntrl-C). 66 ; 03 Sep 88 Return the character output by INT21/04,05,06 in AL. 67 ; 10 Nov 88 Preserve ES when calling any Device Driver (Revalation DEVDRVR) 68 ; 15 Dec 88 Check STDERR for Control-C if it is a Device. 69 ; 15 Mar 89 Check for CTLC during Cooked Write. 70 ; 16 Mar 89 Explicitly allow INT 28 during char reads (SmartNotes bug) 71 ; 25 Apr 89 Execute break_check after getting the console status INT21/0B 72 ; 2 May 89 Save Device driver STRAT and INT address's on the stack 73 ; 10 May 89 Now check keyboard more often during cooked write 74 ; 25 May 89 Move INT28 flag to PCMIF.PCM 75 ; 6 Sep 89 Enter/Exit critical region round device request 76 ; 26 Oct 89 saving some bytes again... 77 ; 25 Jan 90 Insert IDLE Detection Code 78 ; 29 Jan 90 Int 2A critical section support added to device_callf 79 ; 7 Mar 90 Convert to register preserved function calls 80 ; 27 Mar 90 cooked_write checks STD_OUT for ctl-s ctl-p etc (STD_IN may 81 ; have been redirected) 82 ; 29 Mar 90 preserve BX round device_callf (3+Share CLOCK$ bug) 83 ; 12 Jun 90 get_doshndl parameter BX not AX 84 ; 15 Oct 90 Added support for Return Interim Character flag (see PSP_RIC). 85 ; 26 Oct 90 handle PSP=0 (ie. FCB device I/O) 86 ; 1 mar 91 break_check now goes to con_device, not STDERR 87 ; 17 jun 91 ij fix to cooked_out to avoid status checks if STDOUT redirected 88 89 [list -] 101 102 group PCMDATA PCMODE_DATA GLOBAL_DATA FIXED_DOS_DATA 103 group PCMCODE PCM_CODE PCM_RODATA 104 105 ASSUME DS:PCMDATA 106 107 CIO_CTLP equ 00000001b ; Printer Echo State 108 CIO_HANDLE equ 00000010b ; use handle rather than Int 29 109 CIO_RAW equ 00000100b ; no "cooked_status" checks 110 111 CHECK_EVERY equ 80 ; check keyboard every "n" characters 112 === Switch to base=000000h -> "PCM_CODE" 113 section PCM_CODE public align=1 class=CODE 114 extrn char_error:near 115 extrn device_driver:near 116 extrn dos_entry:near 117 extrn get_dseg:near 118 extrn ifn2dhndl:near 119 extrn int21_entry:near 120 extrn int21_func:near 121 extrn read_line:near 122 extrn ReadTimeAndDate:near 123 extrn reload_registers:near 124 125 ; ***************************** 126 ; *** DOS Function 01 *** 127 ; *** Keybd Input W/Echo *** 128 ; ***************************** 129 ; 130 Public func01 131 func01: 132 ; 133 ; Entry: 134 ; AH == 01h 135 ; Exit: 136 ; AL == char 137 ; 0 00003C2B E87200 call func08 ; Read 1 character from Standard Input 139 ; and check for Control-C 0 00003C2E 92 xchg ax,dx ; echo using common code 141 142 ; ***************************** 143 ; *** DOS Function 02 *** 144 ; *** Display Output *** 145 ; ***************************** 146 ; 147 Public func02 148 func02: 149 ; 150 ; Entry: 151 ; AH == 02h 152 ; DL == char to display 153 ; 0 00003C2F 52 push dx ; char on stack 0 00003C30 16 push ss 0 00003C31 07 pop es 0 00003C32 89E6 mov si,sp ; ES:DX -> character 0 00003C34 B90100 mov cx,1 0 00003C37 E81E02 call stdout_cooked_write ; write character 0 00003C3A 58 pop ax ; recover char 0 00003C3B C3 ret 162 163 ; ***************************** 164 ; *** DOS Function 03 *** 165 ; *** Auxiliary Input *** 166 ; ***************************** 167 ; 168 Public func03 169 func03: 170 ; 171 ; Entry: 172 ; AH == 03h 173 ; Exit: 174 ; AL == Char 175 ; 0 00003C3C BB0300 mov bx,STDAUX ; Read 1 character from Standard AUX 177 f03_10: 0 00003C3F E9BB01 jmp raw_read 179 180 ; ***************************** 181 ; *** DOS Function 04 *** 182 ; *** Auxiliary Output *** 183 ; ***************************** 184 ; 185 Public func04 186 func04: 187 ; 188 ; Entry: 189 ; AH == 04h 190 ; DL == Character to output 191 ; 0 00003C42 BB0300 mov bx,STDAUX ; write the character passed in DL 0 00003C45 EB03 jmp f456common ; to the STDAUX Handle 194 195 ; ***************************** 196 ; *** DOS Function 05 *** 197 ; *** Printer Output *** 198 ; ***************************** 199 ; 200 Public func05 201 func05: 202 ; 203 ; Entry: 204 ; AH == 05h 205 ; DL == character to output to printer 206 ; 0 00003C47 BB0400 mov bx,STDPRN ; write the character passed in DL 208 ; jmp f456common ; to the STDPRN Handle 209 210 f456common: 0 00003C4A 92 xchg ax,dx ; character in AL 212 ; jmp hndl_write 213 214 hndl_write: 215 ;---------- 216 ; On Entry: 217 ; AL = character to write 218 ; BX = handle 219 ; On Exit: 220 ; AL preserved 221 ; 0 00003C4B E80804 call is_device ; Does this handle refer to a device 0 00003C4E 720B jc hndl_w10 224 DEVHDR.ATTRIB equ ATTRIB ; NASM port label 0 00003C50 26F744041000 test word [es:DEVHDR.ATTRIB + si],DA_SPECIAL 0 00003C56 7403 jz hndl_w10 ; Fast Console Output Using Int 29? 0 00003C58 CD29 int 29h ; This device supports FAST console 0 00003C5A C3 ret ; output so write this using Int29 229 230 hndl_w10: 0 00003C5B 50 push ax ; character on stack 0 00003C5C 89E2 mov dx,sp ; SS:DX -> char 0 00003C5E B90100 mov cx,1 ; do a single character 0 00003C61 7205 jc hndl_w20 ; was it a file ? 0 00003C63 E80503 call device_write ; send to device driver 0 00003C66 EB07 jmp hndl_w30 237 hndl_w20: 0 00003C68 16 push ss 0 00003C69 07 pop es ; ES:DX -> character 0 00003C6A B440 mov ah,MS_X_WRITE ; otherwise call the FDOS to do all 0 00003C6C E8[0000] call dos_entry ; the hard work 242 hndl_w30: 0 00003C6F 58 pop ax 0 00003C70 C3 ret 245 246 247 ; ***************************** 248 ; *** DOS Function 06 *** 249 ; *** Direct Console I/O *** 250 ; ***************************** 251 ; 252 Public func06 253 func06: 254 ; 255 ; Entry: 256 ; AH == 06h 257 ; DL == 0FFh or Output char 258 ; Exit: 259 ; AL == Input char, if DL was 0FFh on input 260 ; 0 00003C71 BB0100 mov bx,STDOUT ; Assume output DL to console 0 00003C74 80FAFF cmp dl,0FFH ; or is it input ? 0 00003C77 75D1 jne f456common 0 00003C79 4B dec bx 265 ; mov bx,STDIN ; is there a character ready 0 00003C7A E82903 call char_check ; to be input 0 00003C7D 7419 jz func07 268 0 00003C7F E8D403 call is_device ; reading from file? 0 00003C82 730F jnc func06_10 ; no, exit 0 00003C84 06 push es 0 00003C85 8E06[0000] mov es,[current_psp] ; get current PSP 0 00003C89 26C41E3400 les bx,[es:PSP_XFTPTR] ; file handle table 0 00003C8E 26C60701 mov byte ptr [es:STDIN + bx],1 ; cancel input redirection 0 00003C92 07 pop es 276 func06_10: 277 0 00003C93 B80004 mov ax,RHS_IC ; set AL=0 and also set ZF on 0 00003C96 EB0E jmp funcICexit ; exit as incomplete char 280 281 282 ; ***************************** 283 ; *** DOS Function 07 *** 284 ; *** Raw Input w/o echo *** 285 ; ***************************** 286 ; 287 Public func07 288 func07: 289 ; 290 ; Entry: 291 ; AH == 07h 292 ; Exit: 293 ; AL == character 294 ; 0 00003C98 BB0000 mov bx,STDIN 0 00003C9B E85F01 call raw_read ; extra status call made 0 00003C9E EB06 jmp funcICexit ; set incomplete char 298 299 ; ***************************** 300 ; *** DOS Function 08 *** 301 ; *** Input w/o echo *** 302 ; ***************************** 303 ; 304 Public func08 305 func08: 306 ; 307 ; Entry: 308 ; AH == 08h 309 ; Exit: 310 ; AL == character 311 ; 0 00003CA0 BB0000 mov bx,STDIN ; Read 1 character from Standard Input 0 00003CA3 E87501 call cooked_read 314 funcICexit: 315 ; exit point for incomplete character support 316 ; On Entry: 317 ; AL = character 318 ; AH = request header status (RHS_IC as on return from device driver) 319 ; On Exit: 320 ; AL = character 321 ; dos_FLAGS ZF set if incomplete character 322 ; 0 00003CA6 C43E[0000] les di,[int21regs_ptr] ; point to callers registers 0 00003CAA 26836516BF and word [es:reg_FLAGS + di],word ptr ~ ZERO_FLAG ; clear ZF 0 00003CAF 90 nop ; identicalise 0 00003CB0 F6C404 test ah,RHS_IC/256 ; is it an incomplete char ? 0 00003CB3 7406 jz funcIC10 ; no - exit 0 00003CB5 26834D1640 or word [es:reg_FLAGS + di],word ptr ZERO_FLAG ; yes - set ZF 0 00003CBA 90 nop ; identicalise 330 funcIC10: 0 00003CBB C3 ret 332 333 ; ***************************** 334 ; *** DOS Function 09 *** 335 ; *** Print String *** 336 ; ***************************** 337 ; 338 Public func09 339 func09: 340 ; 341 ; Entry: 342 ; AH == 09h 343 ; DS:DX == address of character string 344 ; 345 0 00003CBC B024 mov al,'$' ; it's terminated with a '$' 0 00003CBE 89D7 mov di,dx ; locate the end of the string 0 00003CC0 B9FFFF mov cx,0FFFFh ; and calculate its length 0 00003CC3 F2AE repnz scasb 0 00003CC5 F7D1 not cx 0 00003CC7 49 dec cx ; CX is the character count 0 00003CC8 89D6 mov si,dx 0 00003CCA E88B01 call stdout_cooked_write ; ES:SI -> character buffer 0 00003CCD B024 mov al,'$' 0 00003CCF C3 ret 356 357 358 ; ***************************** 359 ; *** DOS Function 0A *** 360 ; *** Read String *** 361 ; ***************************** 362 ; 363 Public func0A 364 func0A: 365 ; 366 ; Entry: 367 ; AH == 0Ah 368 ; DS:DX == pointer to input buffer 369 ; 0 00003CD0 BB0000 mov bx,STDIN ; Read the editted line from STDIN 0 00003CD3 B90100 mov cx,STDOUT ; and display the results on STDOUT 0 00003CD6 E9[0000] jmp read_line ; Read the Line 373 374 ; ***************************** 375 ; *** DOS Function 0B *** 376 ; *** Console Status *** 377 ; ***************************** 378 ; 379 Public func0B 380 func0B: 381 ; 382 ; Entry: 383 ; AH == 0Bh 384 ; Exit: 385 ; AL == 0FFh if char available 386 ; == 00h otherwise 387 ; 0 00003CD9 BB0000 mov bx,STDIN 0 00003CDC E8AB00 call cooked_status ; Get the current handle status 0 00003CDF B0FF mov al,0FFh ; Assume that the handle is ready 0 00003CE1 7402 jz f0B_exit ; and return 0FFh in AL 0 00003CE3 B000 mov al,00 ; Not Ready 393 f0B_exit: 0 00003CE5 EBBF jmp funcICexit ; exit thru incomplete char support 395 396 397 398 ; ***************************** 399 ; *** DOS Function 0C *** 400 ; *** Flush and Execute *** 401 ; ***************************** 402 ; 403 Public func0C 404 func0C: 405 ; 406 ; Entry: 407 ; AH == 0Ch 408 ; AL == function to execute: 1,6,7,8 or A 409 ; Exit: 410 ; AL = 0 if function in AL is invalid 411 ; 0 00003CE7 50 push ax ; save sub-function 0 00003CE8 BB0000 mov bx,STDIN ; Is this Standard Input Handle a 0 00003CEB E86803 call is_device ; file or device. Do not flush the 0 00003CEE 720A jc f0C_20 ; buffer contents for a FILE 416 f0C_10: 0 00003CF0 E81D03 call hndl_instat ; check if any characters are left 0 00003CF3 7505 jnz f0C_20 ; and quit when buffer empty 0 00003CF5 E80501 call raw_read ; read the character 0 00003CF8 EBF6 jmp f0C_10 ; loop till the buffer is empty 421 422 f0C_20: 0 00003CFA 58 pop ax 0 00003CFB 3C01 cmp al,01h 0 00003CFD 740C je al_ok ; is legal for this command 0 00003CFF 3C0A cmp al,0ah 0 00003D01 7408 je al_ok 0 00003D03 3C06 cmp al,06h 0 00003D05 720C jb al_nogo 0 00003D07 3C08 cmp al,08h 0 00003D09 7708 ja al_nogo 432 433 al_ok: ; Valid function so now execute 0 00003D0B E8[0000] call reload_registers ; all register reloaded as per entry 0 00003D0E 88C4 mov ah,al ; Get the requested sub-function in AH 0 00003D10 E9[0000] jmp int21_func ; execute the function 437 438 al_nogo: ; Illegal command to execute 0 00003D13 31C0 xor ax,ax ; from this function so return error 0 00003D15 C3 ret 441 442 ; 443 ; BREAK_CHECK checks for a CNTRL-C and is called by functions 01h to 444 ; 0Ch. Or by the entry code if the break flag is non zero. 445 ; 446 Public break_check 447 break_check: 0 00003D16 803E[0000]01 cmp byte [indos_flag],01 ; Skip the check if we are 0 00003D1B 7513 jnz break_c15 ; already in the emulator 0 00003D1D 50 push ax 0 00003D1E 06 push es 0 00003D1F 56 push si 0 00003D20 C436[0000] les si,[con_device] 0 00003D24 E8F702 call device_instat ; get the input status 0 00003D27 5E pop si 0 00003D28 07 pop es 0 00003D29 7504 jnz break_c10 ; No Character Ready 0 00003D2B 3C03 cmp al,CTLC ; Is the character a Control-C 0 00003D2D 7402 jz break_c20 ; Yes 460 break_c10: 0 00003D2F 58 pop ax 462 break_c15: 0 00003D30 C3 ret 464 465 break_c20: ; The User has Typed Control-C so flush 0 00003D31 BBFFFF mov bx,0FFFFh ; input buffer (FFFF=con_device) 0 00003D34 E80201 call char_get 468 go_int23: 0 00003D37 0E push cs 0 00003D38 07 pop es ; ES:DX -> Character Buffer 0 00003D39 BE[0000] mov si,offset cntrl_c_msg ; Message Offset 0 00003D3C B90400 mov cx,lengthof_cntrl_c_msg ; Message Length 0 00003D3F E81601 call stdout_cooked_write ; write the ^C String to console 474 ; 475 ; Prepare to execute an Interrupt 23 (Break Check) and process 476 ; the return values. If the called routine returns with an IRET 477 ; or with a RETF and the carry flag reset continue the function 478 ; otherwise Abort. 479 ; 0 00003D42 8E06[0000] mov es,[current_psp] ; Get the Entry SS and SP 0 00003D46 26A12E00 mov ax,[es:PSP_USERSP] ; Get the Users Stack Pointer 0 00003D4A 83C010 add ax,18 - 2 ; Compensate for the User Registers 0 00003D4D A3[0000] mov [break_sp],ax ; and save for RETF check 0 00003D50 FA cli 0 00003D51 FE0E[0000] dec byte [indos_flag] ; Exit the PCDOS emulator 0 00003D55 268E163000 mov ss,[es:PSP_USERSS] ; Switch to the Users Stack 0 00003D5A 268B262E00 mov sp,[es:PSP_USERSP] ; and Restore the registers 488 0 00003D5F 585B595A5E5F5D1F07 POP_DOS ; Update the registers then 490 ; set the flags and return 491 ; to the user 0 00003D68 F8 clc ; Default to continue function 0 00003D69 CD23 int 23h ; Call the Break Handler 0 00003D6B FA cli ; Check the Flag State 0 00003D6C 730B jnc do23_10 ; If CARRY then Abort this process 0 00003D6E E8[0000] call get_dseg ; Get our data segment 0 00003D71 C606[0000]01 mov byte [exit_type],TERM_BREAK ; Force EXIT_TYPE to TERM_BREAK 0 00003D76 B8004C mov ax,4C00h ; "Good-Bye Cruel World" 499 ; jmp do23_20 500 do23_10: 0 00003D79 1E push ds ; Otherwise restart the aborted func 0 00003D7A E8[0000] call get_dseg 0 00003D7D 3B26[0000] cmp sp,[break_sp] 0 00003D81 1F pop ds ; Restore the the USER DS correct 0 00003D82 7403 jz do23_30 ; Did we Use a RETF or Not 506 do23_20: 0 00003D84 83C402 add sp,2 ; Yes so correct the stack pointer 508 do23_30: ; and restart the aborted function 0 00003D87 E9[0000] jmp int21_entry ; re-start the function call 510 511 512 513 ; 514 ; cooked_status is called on input or output and looks for live keys ^C,^P,^S. 515 ; If any of these are found they are dealt with. 516 ; If ^P is encountered it is swallowed. 517 ; If ^C is encountered we always do an Int23. 518 ; If ^S is pressed we swallow it, and the next character (checking for ^C, but 519 ; not for ^P), then say a character is ready. 520 ; Note that this can lead to status calls (func0B) hanging inside the OS, 521 ; or the return of ^S characters from input calls (func01), but this is 522 ; intentional. 523 ; 524 525 cooked_status: 526 ;------------- 527 ; check input 528 ; On Entry: 529 ; BX = handle to check 530 ; On Exit: 531 ; ZF set if character available 532 ; AL = character 533 ; AH = RHS_IC 534 ; 0 00003D8A E889FF call break_check ; check for a ^C on console 0 00003D8D E81602 call char_check ; is there a character ready 0 00003D90 7542 jnz cooked_s50 ; no so keep scanning 538 0 00003D92 803E[0000]00 cmp byte [last_key_ext],0 ; was last char an zero ? 0 00003D97 C606[0000]00 mov byte [last_key_ext],0 ; (clear flag for next time) 0 00003D9C 752B jne cooked_s40 ; skip ^P,^S,^C checks if so 542 0 00003D9E 3C10 cmp al,CTLP ; has the user typed ^P 0 00003DA0 750F jne cooked_s10 ; flush the buffer and 0 00003DA2 8036[0000]01 xor byte [cio_state],CIO_CTLP ; toggle ^P flag 0 00003DA7 E88F00 call char_get ; flush the character from buffer 0 00003DAA E8E702 call open_or_close_prn ; open/close printer device 0 00003DAD 85C0 test ax,ax ; ZF clear, ie. no char available 0 00003DAF EB23 jmp cooked_s50 550 551 cooked_s10: 0 00003DB1 3C03 cmp al,CTLC 0 00003DB3 7506 jnz cooked_s30 ; has the user typed ^C 0 00003DB5 E88100 call char_get ; so get the RAW character 555 cooked_s20: 0 00003DB8 E97CFF jmp go_int23 ; and terminate the function 557 558 cooked_s30: 0 00003DBB 3C13 cmp al,CTLS ; pause if the user has typed 0 00003DBD 750A jnz cooked_s40 ; a ^S 0 00003DBF E87700 call char_get ; remove ^S and resume when 0 00003DC2 E83500 call raw_read_wait ; the next character is typed 0 00003DC5 3C03 cmp al,CTLC 0 00003DC7 74EF je cooked_s20 ; has the user typed ^C 565 cooked_s40: 0 00003DC9 3C00 cmp al,0 0 00003DCB 7505 jne cooked_s45 0 00003DCD C606[0000]01 mov byte [last_key_ext],1 569 cooked_s45: 0 00003DD2 39C0 cmp ax,ax ; ZF set, ie. char available 571 cooked_s50: 0 00003DD4 C3 ret 573 574 ; 575 ; The COOKED, CMDLINE and RAW Read functions are basically the same 576 ; except in their treatment of 'live' characters ^C,^P, and ^S. 577 ; COOKED will look for and act upon all three live characters. 578 ; CMDLINE will look for and act upon ^C and ^P, but ^S will be returned 579 ; so we can use it as a line editing key. 580 ; RAW will not check for any live keys. 581 ; 582 public cmdline_read, raw_read ; for CMDLINE.PCM 583 584 cmdline_read_wait: ; Waiting for a device to become 0 00003DD5 E85B01 call idle_dev ; ready. So call IDLE routines to 586 ; put the processor to sleep. 587 cmdline_read: 0 00003DD8 E83BFF call break_check ; check for a ^C on console 0 00003DDB E8C801 call char_check ; is there a character ready 590 ; jnz cmdline_read_wait ; no so keep scanning 0 00003DDE 7416 jz cmdline_read10 ; yes, proceed 0 00003DE0 E87302 call is_device ; reading from file? 0 00003DE3 73F0 jnc cmdline_read_wait ; no, keep scanning 0 00003DE5 06 push es 0 00003DE6 8E06[0000] mov es,[current_psp] ; get current PSP 0 00003DEA 26C41E3400 les bx,[es:PSP_XFTPTR] ; file handle table 0 00003DEF 26C60701 mov byte ptr [es:STDIN + bx],1 ; cancel input redirection 0 00003DF3 07 pop es 0 00003DF4 EBDF jmp cmdline_read_wait 600 cmdline_read10: 0 00003DF6 3C13 cmp al,CTLS ; if the user has typed ^S 0 00003DF8 7521 jne cooked_read ; we have to do a raw read 603 ; jmp raw_read ; else we do a cooked read 604 605 raw_read_wait: ; Waiting for a device to become 0 00003DFA E83601 call idle_dev ; ready. So call IDLE routines to 607 ; put the processor to sleep. 608 raw_read: 0 00003DFD E8A601 call char_check ; Is there a character Ready 610 ; jnz raw_read_wait ; loop until character available 0 00003E00 7437 jz char_get ; yes, proceed 0 00003E02 E85102 call is_device ; reading from file? 0 00003E05 73F3 jnc raw_read_wait ; no, keep scanning 0 00003E07 06 push es 0 00003E08 8E06[0000] mov es,[current_psp] ; get current PSP 0 00003E0C 26C41E3400 les bx,[es:PSP_XFTPTR] ; file handle table 0 00003E11 26C60701 mov byte ptr [es:STDIN + bx],1 ; cancel input redirection 0 00003E15 07 pop es 0 00003E16 EBE2 jmp raw_read_wait 620 ; jmp char_get 621 622 cooked_read_wait: ; Waiting for a device to become 0 00003E18 E81801 call idle_dev ; ready. So call IDLE routines to 624 ; put the processor to sleep. 625 cooked_read: 0 00003E1B E8F8FE call break_check ; check for a ^C on console 0 00003E1E E869FF call cooked_status ; check for a ^S,^P,^C on handle BX 628 ; jnz cooked_read_wait ; wait until char is available 0 00003E21 7416 jz char_get ; yes, proceed 0 00003E23 E83002 call is_device ; reading from file? 0 00003E26 73F0 jnc cooked_read_wait ; no, keep scanning 0 00003E28 06 push es 0 00003E29 8E06[0000] mov es,[current_psp] ; get current PSP 0 00003E2D 26C41E3400 les bx,[es:PSP_XFTPTR] ; file handle table 0 00003E32 26C60701 mov byte ptr [es:STDIN + bx],1 ; cancel input redirection 0 00003E36 07 pop es 0 00003E37 EBDF jmp cooked_read_wait 638 ; jmp char_get ; else get the character 639 640 char_get: 0 00003E39 06 push es 0 00003E3A 50 push ax ; Input one character and 0 00003E3B 89E2 mov dx,sp ; return it in AL 0 00003E3D E81602 call is_device ; Does this handle refer to a device 0 00003E40 B90100 mov cx,1 0 00003E43 7206 jc char_get30 ; if it's a device then 0 00003E45 E81F01 call device_read ; use device_read 648 char_get20: 0 00003E48 58 pop ax 0 00003E49 07 pop es 0 00003E4A C3 ret 652 653 char_get30: 654 ; We are redirected, so call to the FDOS to get a character 0 00003E4B 58 pop ax ; get previous status 0 00003E4C 30E4 xor ah,ah ; clear AH so that it is not mistaken 0 00003E4E 50 push ax ; for a device request header 0 00003E4F 16 push ss 0 00003E50 07 pop es ; EX:DX -> character to read 0 00003E51 B43F mov ah,MS_X_READ ; call the FDOS to do all 0 00003E53 E8[0000] call dos_entry ; the hard work 0 00003E56 EBF0 jmp char_get20 663 664 665 stdout_cooked_write: 0 00003E58 BB0100 mov bx,STDOUT ; output to the console device 667 ; jmp cooked_write 668 669 ; 670 ; The COOKED_WRITE routine will expand TABS etc in the string 671 ; passed passed by the calling routine. 672 ; 673 ; On Entry: 674 ; ES:SI Buffer Address 675 ; CX Character Count 676 ; BX Output Handle 677 ; On Exit: 678 ; AL = last char written 679 ; 680 Public cooked_write 681 cooked_write: 0 00003E5B 06 push es 0 00003E5C 53 push bx 0 00003E5D 8A26[0000] mov ah,[cio_state] ; get CIO_CTLP status 0 00003E61 80CC06 or ah,CIO_RAW+CIO_HANDLE ; assume we will want raw handle output 0 00003E64 88D8 mov al,bl 0 00003E66 F606[0100]80 test byte [remote_call+1],DHM_FCB/100h 0 00003E6B 7513 jnz cook_w03 0 00003E6D 8E06[0000] mov es,[current_psp] ; get our PSP 0 00003E71 263B1E3200 cmp bx,[es:PSP_XFNMAX] ; range check our handle 0 00003E76 7333 jae cook_w05 0 00003E78 26C43E3400 les di,[es:PSP_XFTPTR] 0 00003E7D 268A01 mov al,byte ptr [es:bx+di] ; AL = Internal File Handle 694 cook_w03: 0 00003E80 E8[0000] call ifn2dhndl ; ES:BX -> DHNDL_ 0 00003E83 7226 jc cook_w05 ; skip if bad handle 0 00003E85 268B5705 mov dx,[es:DHNDL_WATTR + bx] ; get handle attributes 0 00003E89 81E2A380 and dx,DHAT_DEV+DHAT_CIN+DHAT_COT+DHAT_BIN+DHAT_REMOTE 0 00003E8D 81FAA300 cmp dx,DHAT_DEV+DHAT_CIN+DHAT_COT+DHAT_BIN 0 00003E91 7409 je cook_w04 ; accept binary console device 0 00003E93 81FA8300 cmp dx,DHAT_DEV+DHAT_CIN+DHAT_COT 0 00003E97 7512 jne cook_w05 ; skip if not cooked console device 0 00003E99 80E4FB and ah,~ CIO_RAW ; we want cooked output 704 cook_w04: 0 00003E9C 26C45F07 les bx,[es:DHNDL_DEVPTR + bx] ; its the console - but is it FAST ? 0 00003EA0 26F747041000 test word [es:DEVHDR.ATTRIB + bx],DA_SPECIAL 0 00003EA6 7403 jz cook_w05 ; skip if not 0 00003EA8 80E4FD and ah,~ CIO_HANDLE ; don't use handle functions 709 cook_w05: 0 00003EAB 5B pop bx 0 00003EAC 07 pop es 0 00003EAD E34F jcxz cook_w80 713 cook_w10: 0 00003EAF 26AC es lodsb ; Read the next character 0 00003EB1 3C7F cmp al,DEL 0 00003EB3 7444 je cook_w60 ; DEL is a NON Printing Character 0 00003EB5 3C20 cmp al,' ' 0 00003EB7 733C jae cook_w50 ; Space and Above are Normal 0 00003EB9 3C0A cmp al,LF 0 00003EBB 743C je cook_w60 ; Just print LineFeeds 0 00003EBD 3C1B cmp al,ESC 0 00003EBF 7438 je cook_w60 ; Just print Escape 0 00003EC1 3C07 cmp al,BELL 0 00003EC3 7434 je cook_w60 ; Just ring the Bell 0 00003EC5 3C0D cmp al,CR 0 00003EC7 750C jne cook_w20 ; CR zeros the column number 0 00003EC9 C606[0000]00 mov byte [column],0 0 00003ECE C606[0000]01 mov byte [char_count],1 ; check for ^S etc NOW 0 00003ED3 EB24 jmp cook_w60 730 cook_w20: 0 00003ED5 3C08 cmp al,CTLH 0 00003ED7 7506 jne cook_w30 ; BackSpace decrements the 0 00003ED9 FE0E[0000] dec byte [column] ; column count by one 0 00003EDD EB1A jmp cook_w60 735 cook_w30: 0 00003EDF 3C09 cmp al,TAB 0 00003EE1 7516 jne cook_w60 ; is it a TAB ? 738 cook_w40: 0 00003EE3 B020 mov al,' ' ; spaces 0 00003EE5 E81700 call cooked_out ; output a space char 0 00003EE8 FE06[0000] inc byte [column] 0 00003EEC F606[0000]07 test byte [column],7 ; are we at a TAB stop yet ? 0 00003EF1 75F0 jnz cook_w40 0 00003EF3 EB07 jmp cook_w70 745 cook_w50: 0 00003EF5 FE06[0000] inc byte [column] ; Update the column count and 747 cook_w60: 0 00003EF9 E80300 call cooked_out ; output the character 749 cook_w70: 0 00003EFC E2B1 loop cook_w10 ; onto the next character 751 cook_w80: 0 00003EFE C3 ret 753 754 cooked_out: 755 ; On Entry: 756 ; AH = handle status 757 ; AL = character 758 ; BX = handle 759 ; On Exit: 760 ; AX, BX, CX, ES:SI preserved 761 ; 0 00003EFF FE0E[0000] dec byte [char_count] ; time to check keyboard input ? 0 00003F03 7408 jz cooked_o10 ; no, skip status check 0 00003F05 F6C403 test ah,CIO_HANDLE+CIO_CTLP ; is it complicated ? 0 00003F08 7503 jnz cooked_o10 0 00003F0A CD29 int 29h ; This device supports FAST console 0 00003F0C C3 ret 768 769 cooked_o10: 0 00003F0D 06 push es 0 00003F0E 50 push ax 0 00003F0F 51 push cx 0 00003F10 56 push si 0 00003F11 E837FD call hndl_write ; display the character 0 00003F14 F6C401 test ah,CIO_CTLP ; Check for Printer Echo 0 00003F17 7408 jz cooked_o20 ; Off so No Echo 0 00003F19 53 push bx ; Save Output Handle 0 00003F1A BB0400 mov bx,STDPRN ; and output the same data to the 0 00003F1D E82BFD call hndl_write ; to the Printer Handle 0 00003F20 5B pop bx 781 cooked_o20: 0 00003F21 F6C404 test ah,CIO_RAW ; is it a cooked console ? 0 00003F24 7508 jnz cooked_o30 ; skip check if not 0 00003F26 E861FE call cooked_status ; look for keyboard input 0 00003F29 C606[0000]50 mov byte [char_count],CHECK_EVERY ; look again in a while 786 cooked_o30: 0 00003F2E 5E pop si 0 00003F2F 59 pop cx 0 00003F30 58 pop ax 0 00003F31 07 pop es 0 00003F32 C3 ret 792 793 ; IDLE_DEV is called when the PCMODE is waiting for a character. 794 ; This routine must determine if the request is for a device or not 795 ; and call the IDLE interface for device requests to the system can be 796 ; put to sleep until a character is ready. 797 ; 798 ; On Entry:- BX Handle Number 799 ; 800 idle_dev: 0 00003F33 53 push bx ; preserve handle 0 00003F34 B80084 mov ax,8400h 0 00003F37 CD2A int 2ah ; Server hook for idle 0 00003F39 FE0E[0000] dec byte [clock_count] 0 00003F3D 7503 jnz idle_dev10 ; Zero if NO skip delay and execute 0 00003F3F E8[0000] call ReadTimeAndDate ; for PC BIOS's who must read every day 807 idle_dev10: 808 %if IDLE_DETECT 0 00003F42 F706[0000]00C0 test word [idle_flags],IDLE_DISABLE ; Has Idle Checking been enabled 0 00003F48 751B jnz idle_dev40 ; Skip if NO 0 00003F4A 06 push es 0 00003F4B 56 push si 0 00003F4C E80701 call is_device ; The requested handle a file or device 0 00003F4F 7212 jc idle_dev30 ; File Access skip IDLE 0 00003F51 B80300 mov ax,PROC_KEYIN ; Assume this is the REAL Console 0 00003F54 26F744040100 test word [es:DEVHDR.ATTRIB + si],DA_ISCIN; Test Attribute Bits 0 00003F5A 7503 jnz idle_dev20 ; Yes this is Default Console Device 0 00003F5C B80400 mov ax,PROC_DEVIN ; Input from Another Device 819 idle_dev20: 0 00003F5F FF1E[0000] call far [idle_vec] ; Call the IDLE Handler 821 idle_dev30: 0 00003F63 5E pop si 0 00003F64 07 pop es 824 idle_dev40: 825 %endif 0 00003F65 5B pop bx ; recover handle 0 00003F66 C3 ret 828 829 ; The following routine reads CX bytes from the device whose address 830 ; is held in the DWORD pointer passed by DS:SI. A Request Header 831 ; is built on the stack and the command is executed. 832 ; 833 ; On Entry: 834 ; ES:SI DWORD Pointer to Device Header 835 ; SS:DX Buffer Address 836 ; CX Character Count 837 ; 838 ; On Exit: 839 ; AX Request Header Status 840 ; Zero No Error 841 ; 842 Public device_read 843 device_read: 0 00003F67 B004 mov al,CMD_INPUT ; we want input 0 00003F69 EB02 jmp device_common ; now use common code 846 847 ; The following routine writes CX bytes to the device whose address 848 ; is held in the DWORD pointer passed by DS:SI. A Request Header 849 ; is built on the stack and the command is executed. 850 ; 851 ; On Entry: 852 ; ES:SI DWORD Pointer to Device Header 853 ; SS:DX Buffer Address 854 ; CX Character Count 855 ; 856 ; On Exit: 857 ; AX Request Header Status 858 ; Zero No Error 859 ; 860 Public device_write 861 device_write: 0 00003F6B B008 mov al,CMD_OUTPUT ; we want output 863 device_common: 0 00003F6D 53 push bx 0 00003F6E 83EC1E sub sp,RH4_LEN ; reserve space on the stack 0 00003F71 89E3 mov bx,sp ; request header offset 0 00003F73 36C6071E mov byte [ss:RH_LEN + bx],RH4_LEN ; request header length 0 00003F77 3689570E mov [ss:RH4_BUFOFF + bx],dx ; buffer offset 0 00003F7B 368C5710 mov [ss:RH4_BUFSEG + bx],ss ; buffer segment 870 device_common10: 0 00003F7F 36894F12 mov [ss:RH4_COUNT + bx],cx ; character count 0 00003F83 E8B300 call device_req ; execute command 0 00003F86 7916 jns device_common20 ; if no errors return to the caller 0 00003F88 362B4F12 sub cx,[ss:RH4_COUNT + bx] ; CX = chars remaining 0 00003F8C 50 push ax ; save the error code 0 00003F8D E8[0000] call char_error ; ask int 24 what to do 0 00003F90 3C01 cmp al,ERR_RETRY ; should we retry the operation ? 0 00003F92 58 pop ax ; recover the error code 0 00003F93 7709 ja device_common20 ; Fail/Abort return error 0 00003F95 368A4702 mov al,[ss:RH_CMD + bx] ; reload the command 0 00003F99 74E4 je device_common10 ; Retry, re-issue the device request 0 00003F9B B80001 mov ax,RHS_DONE ; Ignore, pretend no errors 883 device_common20: 0 00003F9E 83C41E add sp,RH4_LEN ; restore the stack to its normal 0 00003FA1 A90080 test ax,RHS_ERROR ; state and return the status. 0 00003FA4 5B pop bx 0 00003FA5 C3 ret 888 889 890 char_check: 891 ; On Entry: 892 ; BX = handle to check 893 ; On Exit: 894 ; ZF set if character ready 895 ; AL = character (if device handle) 896 ; AH = RIC status 897 ; 0 00003FA6 53 push bx ; Save the current handle status 899 %if IDLE_DETECT 0 00003FA7 F706[0000]00C0 test word [idle_flags],IDLE_DISABLE ; Has Idle Checking been enabled 0 00003FAD 7513 jnz char_check10 ; Skip if NO 0 00003FAF FF0E[0000] dec word [int28_delay] ; Has the INT28 Loop count reached 0 00003FB3 750D jnz char_check10 ; Zero if NO skip delay and execute 0 00003FB5 A1[0000] mov ax,[int28_reload] ; INT28. Otherwise DELAY/DISPATCH 0 00003FB8 A3[0000] mov [int28_delay],ax 0 00003FBB B80200 mov ax,PROC_INT28 ; Process is IDLE 0 00003FBE FF1E[0000] call far [idle_vec] ; Call the IDLE Handler 908 char_check10: 909 %endif 0 00003FC2 803E[0000]01 cmp byte [indos_flag],1 ; Only execute an INT 28 0 00003FC7 7546 jnz char_check20 ; when the INDOS flag is 1 0 00003FC9 803E[0000]FF cmp byte [int28_flag],TRUE & 0FFh ; Only generate INT 28s for the 0 00003FCE 753F jnz char_check20 ; selected functions 914 0 00003FD0 FF36[0000] push word [remote_call] 0 00003FD4 FF36[0000] push word [machine_id] 0 00003FD8 8E06[0000] mov es,[current_psp] ; Get the PSP 0 00003FDC 26FF362E00 push word [es:PSP_USERSP] ; Save the SS:SP pointer to 0 00003FE1 26FF363000 push word [es:PSP_USERSS] ; the register image 920 921 %if IDLE_DETECT ; Set IDLE_INT28 so $IDLE$ knows 0 00003FE6 830E[0000]04 or word [idle_flags],word ptr IDLE_INT28 ; that we are nolonger inside DOS 0 00003FEB 90 nop ; identicalise 924 %endif 0 00003FEC CD28 int 28h ; Execute an INT 28 for SideKick and 926 ; the PRINT utility. INDOS flag is 1 927 928 %if IDLE_DETECT ; Reset IDLE_INT28 so $IDLE$ knows 0 00003FEE 8326[0000]FB and word [idle_flags],word ptr ~ IDLE_INT28; that we are back DOS 0 00003FF3 90 nop ; identicalise 931 %endif 0 00003FF4 C606[0000]FF mov byte [int28_flag],TRUE & 0FFh ; Restore INT28_FLAG 0 00003FF9 8E06[0000] mov es,[current_psp] ; Get the PSP 0 00003FFD 268F063000 pop word [es:PSP_USERSS] ; Restore the SS:SP pointer to 0 00004002 268F062E00 pop word [es:PSP_USERSP] ; the register image 0 00004007 8F06[0000] pop word [machine_id] 0 0000400B 8F06[0000] pop word [remote_call] 938 char_check20: 0 0000400F 5B pop bx 940 ; jmp hndl_instat ; Check Input Status. ZERO == Ready 941 942 ; 943 ; 944 hndl_instat: 0 00004010 E84300 call is_device ; Does this handle refer to a device 0 00004013 7309 jnc device_instat 0 00004015 B80644 mov ax,(MS_X_IOCTL << 8)+6 ; Get the file status 0 00004018 E8[0000] call dos_entry ; for the specified handle 0 0000401B 3CFF cmp al,0FFh ; and return ZERO until the EOF 0 0000401D C3 ret 951 952 ; The following routine executes the Non Destructive Input 953 ; command to the device whose address passed in ES:SI. 954 ; 955 ; On Entry: 956 ; ES:SI DWORD Pointer to Device Header 957 ; 958 ; On Exit: 959 ; Zero Character Ready 960 ; AH Top Byte Request Header Status 961 ; AL Next Character if ZERO 962 ; 963 964 device_instat: 0 0000401E 53 push bx 0 0000401F 83EC0E sub sp,RH5_LEN ; Reserve Space on the Stack 0 00004022 89E3 mov bx,sp ; Request Header Offset 0 00004024 36C6070E mov byte [ss:RH_LEN + bx],RH5_LEN ; Set Request Header Length 0 00004028 B005 mov al,CMD_INPUT_NOWAIT ; Command Number 0 0000402A E80C00 call device_req ; Execute the Command 0 0000402D 368A470D mov al,[ss:RH5_CHAR + bx] ; Assume a character is ready 0 00004031 83C40E add sp,RH5_LEN ; Restore the Stack to its normal 0 00004034 A90002 test ax,RHS_BUSY ; state and return the status. 0 00004037 5B pop bx ; Zero if a Character is ready 0 00004038 C3 ret 976 977 ; The following routine handles the low level device interface to 978 ; the character device drivers. All the generic Request Header 979 ; initialization is carried out here. 980 ; 981 ; On Entry: 982 ; AL Command 983 ; ES:SI Device Header 984 ; SS:BX Current Request Header 985 ; 986 ; On Exit: 987 ; AX Request Header Status 988 ; 989 990 device_req: 991 ;---------- 0 00004039 36884702 mov [ss:RH_CMD + bx],al ; save the command 0 0000403D 1E push ds 0 0000403E 06 push es 0 0000403F 06 push es 0 00004040 1F pop ds ; DS:SI -> device driver 0 00004041 368E06[0000] mov es,[ss:current_psp] ; es = current PSP 0 00004046 26A03C00 mov al,[es:PSP_RIC] ; al = Return Interim Character flag 0 0000404A 3688470D mov [ss:RH4_RIC + bx],al ; Return Interim Char flag 0 0000404E 16 push ss 0 0000404F 07 pop es ; ES:BX -> RH_ 0 00004050 E8[0000] call device_driver 0 00004053 07 pop es 0 00004054 1F pop ds 0 00004055 C3 ret 1006 1007 ; 1008 ; IS_DEVICE checks the internal handle structures to determine 1009 ; if the handle referenced in BX is a file or device. Invalid 1010 ; handles all map to the default console device. 1011 ; 1012 ; On Entry: 1013 ; BX Handle Number 1014 ; 1015 ; On Exit: 1016 ; CY set if handle is for a file 1017 ; CY clear if handle is for device at ES:SI 1018 ; 1019 is_device: 0 00004056 50 push ax 0 00004057 53 push bx ; Convert the Standard Handle number 0 00004058 89D8 mov ax,bx ; get XFN in AL 1023 ; mov cx,current_psp ; into an internal handle number 1024 ; jcxz is_dev10 ; no PSP, we have IFN already 1025 ; mov es,cx 0 0000405A F606[0100]80 test byte [remote_call+1],DHM_FCB/100h; if FCB initiated access 0 0000405F 7513 jnz is_dev10 ; we have IFN already 0 00004061 8E06[0000] mov es,[current_psp] 0 00004065 263B1E3200 cmp bx,[es:PSP_XFNMAX] ; Check if the handle is in range for 0 0000406A 7322 jae is_dev_bad ; this PSP. 0 0000406C 26C4363400 les si,[es:PSP_XFTPTR] 0 00004071 268A00 mov al,byte ptr [es:bx+si] ; AL = Internal File Handle 1033 is_dev10: 0 00004074 E8[0000] call ifn2dhndl ; ES:BX -> DHNDL_ 0 00004077 7215 jc is_dev_bad 0 00004079 268B4705 mov ax,[es:DHNDL_WATTR + bx] ; get file attributes 0 0000407D 258080 and ax,DHAT_REMOTE+DHAT_DEV 0 00004080 3D8000 cmp ax,DHAT_DEV ; is it a local device ? 0 00004083 F9 stc ; assume it's a file 0 00004084 7505 jne is_dev30 0 00004086 26C47707 les si,[es:DHNDL_DEVPTR + bx] ; its a device 1042 is_dev20: 0 0000408A F8 clc 1044 is_dev30: 0 0000408B 5B pop bx 0 0000408C 58 pop ax 0 0000408D C3 ret 1048 1049 is_dev_bad: 0 0000408E C436[0000] les si,[con_device] ; bad handles map to console 0 00004092 EBF6 jmp is_dev20 1052 1053 open_or_close_prn: 1054 ;----------------- 1055 ; called when CIO_CTLP toggled - call prn device with Open or Close as appropriate 1056 ; 0 00004094 1E push ds 0 00004095 50 push ax 0 00004096 53 push bx 0 00004097 B81000 mov ax,CTLP 0 0000409A 50 push ax ; ^P on stack 0 0000409B 8B0E[0000] mov cx,[current_psp] ; look in PSP 0 0000409F E36C jcxz oc_prn30 ; no PSP, forget it 0 000040A1 8EC1 mov es,cx 0 000040A3 263B1E3200 cmp bx,[es:PSP_XFNMAX] ; Check if the handle is in range for 0 000040A8 7363 jae oc_prn30 ; this PSP. 0 000040AA 26C4363400 les si,[es:PSP_XFTPTR] ; for the internal handle number 0 000040AF 268A4404 mov al,byte ptr [es:STDPRN + si] 0 000040B3 3CFF cmp al,0FFh ; AL = Internal File Handle 0 000040B5 7456 je oc_prn30 ; skip if invalid Handle Number 0 000040B7 E8[0000] call ifn2dhndl ; ES:BX -> doshndl 0 000040BA 7251 jc oc_prn30 0 000040BC 26F747050008 test word [es:DHNDL_WATTR + bx],DHAT_NETPRN 0 000040C2 7413 jz oc_prn10 0 000040C4 B82611 mov ax,I2F_CTLP ; turn on the network printer 0 000040C7 CD2F int 2fh ; with a magic INT 2F call 0 000040C9 730C jnc oc_prn10 0 000040CB 8026[0000]FE and byte [cio_state],~ CIO_CTLP ; make sure Printer Echo is off 0 000040D0 B82411 mov ax,I2F_CTLP_ERR 0 000040D3 CD2F int 2fh 0 000040D5 EB36 jmp oc_prn30 1082 oc_prn10: 0 000040D7 268B4705 mov ax,[es:DHNDL_WATTR + bx] ; get file attributes 0 000040DB 258080 and ax,DHAT_REMOTE+DHAT_DEV 0 000040DE 3D8000 cmp ax,DHAT_DEV ; is it a local device ? 0 000040E1 752A jne oc_prn30 0 000040E3 B00D mov al,CMD_DEVICE_OPEN ; assume we've just opened 0 000040E5 F606[0000]01 test byte [cio_state],CIO_CTLP ; Check for Printer Echo 0 000040EA 7502 jnz oc_prn20 ; yes, skip next bit 0 000040EC B00E mov al,CMD_DEVICE_CLOSE ; no, we must close 1091 oc_prn20: 0 000040EE 26C47707 les si,[es:DHNDL_DEVPTR + bx] ; get the device driver address 0 000040F2 26F744040008 test word [es:DEVHDR.ATTRIB + si],DA_REMOVE 0 000040F8 7413 jz oc_prn30 ; no, skip call if not supported 0 000040FA 83EC0D sub sp,RH13_LEN ; Reserve Space on the Stack 0 000040FD 89E3 mov bx,sp ; and point to it 0 000040FF 36C6070D mov byte [ss:RH_LEN + bx],RH13_LEN ; Set Request Header Length 0 00004103 36884702 mov [ss:RH_CMD + bx],al ; Command Number 0 00004107 E8[0000] call device_driver ; issue the command 0 0000410A 83C40D add sp,RH13_LEN ; Restore the Stack to its normal 1101 oc_prn30: 0 0000410D 58 pop ax ; discard ^P from stack 0 0000410E 5B pop bx 0 0000410F 58 pop ax 0 00004110 1F pop ds 0 00004111 C3 ret 1107 PCM_CODE ends 1108 === Switch to base=000000h -> "PCM_RODATA" 1109 section PCM_RODATA public align=2 class=CODE 1110 0 0000B952 5E430D0A cntrl_c_msg db '^C', CR, LF ; Control-Break Message 1112 lengthof_cntrl_c_msg equ $ - cntrl_c_msg 1113 1114 PCM_RODATA ends 1115 === Switch to base=00C180h -> "GLOBAL_DATA" 1116 section GLOBAL_DATA public align=2 class=DATA 1117 0 000012B8 00 clock_count db 0 1119 1120 GLOBAL_DATA ends 1121 === Switch to base=00C180h -> "PCMODE_DATA" 1122 section PCMODE_DATA public align=2 class=DATA 1123 1124 extrn break_sp:word ; For Control-Break handler 1125 extrn char_count:byte 1126 extrn cio_state:byte ; Character I/O State 1127 extrn column:byte ; Console Cursor Location 1128 extrn con_device:dword ; Current Console Device 1129 extrn current_psp:word ; Current PSP Address 1130 extrn exit_type:byte 1131 extrn indos_flag:byte ; INDOS Count 1132 extrn int21regs_ptr:dword ; pointer to callers registers 1133 extrn machine_id:word 1134 extrn remote_call:word 1135 %if IDLE_DETECT 1136 extrn idle_flags:word ; IDLE State Flags 1137 extrn idle_vec:dword ; IDLE routine Vector 1138 extrn int28_delay:word 1139 extrn int28_reload:word 1140 extrn int28_flag:byte 1141 %endif 1142 PCMODE_DATA ends 1143 === Switch to base=00C180h -> "FIXED_DOS_DATA" 1144 section FIXED_DOS_DATA public align=2 class=DATA 1145 extrn last_key_ext:byte 1146 FIXED_DOS_DATA ends 1147 1148 end === Trace listing source: drdos/bin/disk.lst 1 ; File : $DISK.ASM$ 2 ; 3 ; Description : 4 ; 5 ; Original Author : DIGITAL RESEARCH 6 ; 7 ; Last Edited By : $CALDERA$ 8 ; 9 ;-----------------------------------------------------------------------; 10 ; Copyright Work of Caldera, Inc. All Rights Reserved. 11 ; 12 ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, 13 ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. 14 ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES 15 ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF 16 ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO 17 ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE 18 ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE 19 ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, 20 ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, 21 ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, 22 ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF 23 ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT 24 ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND 25 ; CIVIL LIABILITY. 26 ;-----------------------------------------------------------------------; 27 ; 28 ; *** Current Edit History *** 29 ; *** End of Current Edit History *** 30 ; 31 ; $Log$ 32 ; DISK.A86 1.26 94/12/01 10:05:21 33 ; added attribute support for open/move/unlink during server call 34 ; DISK.A86 1.24 93/11/16 13:46:21 35 ; Generate critical error on int21/36 (get free space) 36 ; DISK.A86 1.23 93/10/25 21:58:02 37 ; Tighten up error checks on int21/6C modes (DL bits 0-3 = 3 rejected) 38 ; DISK.A86 1.22 93/10/18 17:40:51 39 ; fix for >255 open files (PNW Server) 40 ; DISK.A86 1.21 93/09/03 20:28:02 41 ; Add "no critical errors" support (int 21/6C) 42 ; DISK.A86 1.20 93/08/04 15:15:15 43 ; Int21/6C allows DH=1 44 ; DISK.A86 1.19 93/07/22 20:32:12 45 ; don't check AL on int 21/6c 46 ; DISK.A86 1.18 93/07/22 19:28:02 47 ; correct bug in extended open/create 48 ; DISK.A86 1.15 93/06/23 04:05:38 49 ; more int21/6C - we still need no critical errors support 50 ; DISK.A86 1.14 93/06/23 03:00:27 51 ; fix bug in int21/6C 52 ; DISK.A86 1.13 93/05/07 15:09:29 53 ; Move delwatch free space adjust call inside the MXDisk 54 ; DISK.A86 1.12 93/03/16 22:33:49 55 ; UNDELETE support changes 56 ; DISK.A86 1.11 93/03/05 18:10:55 57 ; Add UNDELETE definition 58 ; ENDLOG 59 ; 60 ; All FCB based PCMODE functions are translated to FDOS function 61 ; calls in this file. 62 ; 63 ; 22 May 87 Support the extended CHMOD function to get/set the 64 ; password mode. 65 ; 28 May 87 Support the Update Handle Count Function 66 ; 5 Nov 87 Remove MAJOR_VER reference from func0D 67 ; 15 Mar 88 Return Attributes in CX and AX 68 ; 3 May 88 Return correct disk size from functions 1B, 1C and 36 69 ; 17 May 88 Add valid drive check routine used by FUNC29 and FUNC4B 70 ; 30 Jun 88 Call FDOS to build DDSC for INT21/53 71 ; 18 Aug 88 FUNC67 correctly fill new handle table with 0FFh 72 ; Sorcim ACCPAC Plus 73 ; 27 Sep 88 Return error codes from Read and Write Random. 74 ; 19 Feb 89 Allowing SHARE to be disabled with DR DOS 75 ; 16 May 89 Include Random Record field on func23 (file size) 76 ; 23 May 89 func3F (Read) now allows Ignore on errors (CopyIIpc) 77 ; 11 Sep 89 MSNET Flush hook added 78 ; 20 Sep 89 func3B "d:=" form fills in LDT (func4B support) 79 ; 24 Oct 89 func32 (getdpb) sets top bit of drive on fdos_getdpb 80 ; to indicate free space count not required 81 ; 27 Oct 89 mutilate the code to save space 82 ; 24 Jan 90 valid_drive uses dos_entry, doesn't peek at HDS's 83 ; 8 Feb 90 func_43 updated for new password support 84 ; 27 Feb 90 func57 gives ED_FUNCTION if not get/set (HEADROOM bug) 85 ; 7 Mar 90 Convert to register preserved function calls 86 ; 14 Mar 90 Share func3D_mask bodge move to FDOS 87 ; 28 Sep 90 Return sectors xfered on Int21/27 even if error (CALC.EXE>64k) 88 ; 14 mar 91 add delwatch hook to func36 (disk free space) 89 ; 14 jun 91 correct error codes from func3F during func4B 90 ; 8 aug 91 func3B (chdir) now maintains LDT name for all cases 91 ; 1 oct 91 Valdivar it 92 ; 27 feb 92 func3E returns previous open count 93 ; 3 mar 92 fill in default search attribute in Func3D for future 94 ; 23 mar 92 func67 will now shrink #handles 95 ; 96 97 group PCMDATA PCMODE_DATA FDOS_DSEG GLOBAL_DATA BDOS_DATA 98 group PCMCODE PCM_CODE 99 100 ASSUME DS:PCMDATA 101 102 [list -] 112 113 FCB_LEN equ 32 114 XFCB_LEN equ FCB_LEN+7 115 === Switch to base=00C180h -> "BDOS_DATA" 116 section BDOS_DATA public align=2 class=DATA 117 extrn dosfat:word 118 BDOS_DATA ends 119 === Switch to base=000000h -> "PCM_CODE" 120 section PCM_CODE public align=1 class=CODE 121 extrn dbcs_lead:near 122 extrn dos_entry:near 123 extrn fdos_nocrit:near 124 extrn fdos_crit:near, fdos_ax_crit:near 125 extrn fcbfdos_crit:near 126 extrn set_retry:near 127 extrn set_retry_RF:near 128 extrn error_exit:near 129 extrn error_ret:near 130 extrn fcberror_exit:near 131 132 extrn reload_registers:near 133 extrn reload_ES:near 134 extrn return_AX_CLC:near 135 extrn return_BX:near 136 extrn return_CX:near 137 extrn return_DX:near 138 extrn output_hex:near 139 140 ; ***************************** 141 ; *** DOS Function 0D *** 142 ; *** Disk Reset *** 143 ; ***************************** 144 ; 145 Public func0D 146 func0D: 0 00004112 C706[0000]4900 mov word [FD_FUNC],FD_FLUSH 0 00004118 E8[0000] call fdos_nocrit ; flush buffers 0 0000411B B8FFFF mov ax,0FFFFh 0 0000411E 50 push ax 0 0000411F B82011 mov ax,I2F_FLUSH 0 00004122 CD2F int 2fh ; magic INT2F flush remote buffers 0 00004124 58 pop ax 0 00004125 16 push ss 0 00004126 1F pop ds 0 00004127 C3 ret 157 158 ; ***************************** 159 ; *** DOS Function 0E *** 160 ; *** Select Disk *** 161 ; ***************************** 162 ; 163 Public func0E 164 func0E: 165 ; 166 ; Entry: 167 ; DL == drive to set as default (0 == A:) 168 ; Exit: 169 ; AL == Number of Drives in System (from SYSDAT) 170 ; 0 00004128 C706[0000]4A00 mov word [FD_FUNC],FD_SELECT 0 0000412E 92 xchg ax,dx ; drive in AL 0 0000412F 98 cbw ; make that AX 0 00004130 A3[0200] mov [FD_DRIVE],ax 0 00004133 E8[0000] call fdos_nocrit ; ask the FDOS to try to select it 0 00004136 A0[0000] mov al,[last_drv] ; Return the number of valid drives 0 00004139 C3 ret 178 179 ; 180 ; Return with the ZERO flag set if the drive passed in AL is 181 ; valid. This function is used to set the initial AX value 182 ; when a program is loaded. 183 ; 184 ; On Entry:- AL 00 - Default Drive 185 ; 01 to 26 - A: to Z: 186 ; 187 ; On Exit:- ZF If AL referenced a valid drive 188 ; 189 Public valid_drive 190 valid_drive: 0 0000413A 52 push dx 0 0000413B 88C2 mov dl,al ; get drive in DL 0 0000413D FECA dec dl ; make drive zero based 0 0000413F 781A js valid_drive10 ; if current drive always OK 0 00004141 B419 mov ah,MS_DRV_GET 0 00004143 E8[0000] call dos_entry ; get current drive 0 00004146 50 push ax ; save for later 0 00004147 B40E mov ah,MS_DRV_SET 0 00004149 E8[0000] call dos_entry ; try and select new drive 0 0000414C B419 mov ah,MS_DRV_GET ; if we can select it 0 0000414E E8[0000] call dos_entry ; then it's valid 0 00004151 28D0 sub al,dl ; AL = 0 if drive valid 0 00004153 5A pop dx ; recover old drive 0 00004154 50 push ax ; save result 0 00004155 B40E mov ah,MS_DRV_SET 0 00004157 E8[0000] call dos_entry ; reset to original drive 0 0000415A 58 pop ax ; recover result 208 valid_drive10: 0 0000415B 5A pop dx 0 0000415C 84C0 test al,al ; set ZF if valid drive 0 0000415E C3 ret 212 213 ; ***************************** 214 ; *** DOS Function 0F *** 215 ; *** Open File (FCB) *** 216 ; ***************************** 217 ; 218 Public func0F 219 func0F: 220 221 ; ***************************** 222 ; *** DOS Function 10 *** 223 ; *** Close File (FCB) *** 224 ; ***************************** 225 ; 226 Public func10 227 func10: 228 229 ; ***************************** 230 ; *** DOS Function 11 *** 231 ; *** Search First (FCB) *** 232 ; ***************************** 233 ; 234 Public func11 235 func11: 236 237 ; ***************************** 238 ; *** DOS Function 12 *** 239 ; *** Search Next (FCB) *** 240 ; ***************************** 241 ; 242 Public func12 243 func12: 244 245 ; ***************************** 246 ; *** DOS Function 13 *** 247 ; *** Delete File (FCB) *** 248 ; ***************************** 249 ; 250 Public func13 251 func13: 252 253 ; ***************************** 254 ; *** DOS Function 14 *** 255 ; *** Sequential Read (FCB) *** 256 ; ***************************** 257 ; 258 Public func14 259 func14: 260 261 ; ***************************** 262 ; *** DOS Function 15 *** 263 ; *** Sequential Write (FCB)*** 264 ; ***************************** 265 ; 266 Public func15 267 func15: 268 269 ; ***************************** 270 ; *** DOS Function 16 *** 271 ; *** Create File (FCB) *** 272 ; ***************************** 273 ; 274 Public func16 275 func16: 276 277 ; ***************************** 278 ; *** DOS Function 17 *** 279 ; *** Rename File (FCB) *** 280 ; ***************************** 281 ; 282 Public func17 283 func17: 284 285 ; ***************************** 286 ; *** DOS Function 21 *** 287 ; *** Random Read (FCB) *** 288 ; ***************************** 289 ; 290 Public func21 291 func21: 292 293 ; ***************************** 294 ; *** DOS Function 22 *** 295 ; *** Random Write (FCB) *** 296 ; ***************************** 297 ; 298 Public func22 299 func22: 300 301 ; ***************************** 302 ; *** DOS Function 23 *** 303 ; *** File Size (FCB) *** 304 ; ***************************** 305 ; 306 Public func23 307 func23: 308 309 ; ***************************** 310 ; *** DOS Function 24 *** 311 ; *** Set Relative Record *** 312 ; ***************************** 313 ; 314 Public func24 315 func24: 316 317 ; ***************************** 318 ; *** DOS Function 27 *** 319 ; *** Random Block Read *** 320 ; ***************************** 321 ; 322 Public func27 323 func27: 324 325 ; ***************************** 326 ; *** DOS Function 28 *** 327 ; *** Random Block Write *** 328 ; ***************************** 329 ; 330 Public func28 331 func28: 332 ; All FCB function come through here 0 0000415F E8[0000] call set_retry_RF ; Valid to RETRY or FAIL 0 00004162 B84D00 mov ax,FD_FCB ; FCB file function 0 00004165 8706[0000] xchg ax,[FD_FUNC] ; recover function number 0 00004169 A3[0800] mov [FD_FCBFUNC],ax ; pass FCB function number 0 0000416C 8916[0200] mov [FD_FCBOFF],dx ; Initialise the FCB Pointer 0 00004170 8C06[0400] mov [FD_FCBSEG],es 0 00004174 890E[0600] mov [FD_FCBCNT],cx ; we may need record count 0 00004178 E8[0000] call fcbfdos_crit ; Execute the function 0 0000417B 7207 jc fcb_error ; Check for an Error 0 0000417D 8B0E[0600] mov cx,[FD_FCBCNT] ; Get the number of records 0 00004181 E9[0000] jmp return_CX ; processed and return in CX 344 fcb_error: 0 00004184 E9[0000] jmp fcberror_exit ; Use default Error handler 346 347 348 349 ; ***************************** 350 ; *** DOS Function 19 *** 351 ; *** Current Disk *** 352 ; ***************************** 353 354 Public func19 355 func19: 0 00004187 A0[0000] mov al,[current_dsk] ; Get the current logical disk 0 0000418A C3 ret ; and return 358 359 360 ; ***************************** 361 ; *** DOS Function 1A *** 362 ; *** Set Disk Trans Adr *** 363 ; ***************************** 364 365 Public func1A 366 func1A: 0 0000418B 8916[0000] mov [dma_offset],dx ; set the PCMODE DMA Offset 0 0000418F 8C06[0000] mov [dma_segment],es ; and then the DMA Segment 0 00004193 C3 ret 370 371 ; ***************************** 372 ; *** DOS Function 1B *** 373 ; *** Def. Disk Info *** 374 ; ***************************** 375 ; 376 Public func1B 377 func1B: 378 379 ; ***************************** 380 ; *** DOS Function 1C *** 381 ; *** Sel. Disk Info *** 382 ; ***************************** 383 ; 384 Public func1C 385 func1C: 0 00004194 E8[0000] call set_retry_RF ; Valid to RETRY or FAIL 0 00004197 30F6 xor dh,dh ; Pass the drive requested 0 00004199 E8B800 call fdos_DISKINFO ; find out about drive 0 0000419C 722E jc fdos_DI_error 390 0 0000419E 268B4F02 mov cx,[es:DDSC_SECSIZE + bx] ; Get the Physical Sector Size 0 000041A2 E8[0000] call return_CX ; in bytes 393 0 000041A5 268B570D mov dx,[es:DDSC_NCLSTRS + bx] ; Convert the last cluster no 0 000041A9 4A dec dx ; returned in DDSC to maximum 0 000041AA E8[0000] call return_DX ; number of clusters and return 397 0 000041AD 268A4704 mov al,[es:DDSC_CLMSK + bx] ; get (sectors per cluster)-1 0 000041B1 40 inc ax ; return sectors per cluster 0 000041B2 8D5F17 lea bx,[DDSC_MEDIA + bx] ; return address of media byte 401 f1B1C1F32_common: 0 000041B5 1E push ds 0 000041B6 C53E[0000] lds di,[int21regs_ptr] 0 000041BA 8C450E mov [reg_DS + di],es 0 000041BD 895D02 mov [reg_BX + di],bx 0 000041C0 1F pop ds 0 000041C1 C3 ret 408 409 ; ***************************** 410 ; *** DOS Function 1F *** 411 ; *** Get Default DPB *** 412 ; ***************************** 413 ; 414 Public func1F 415 func1F: 416 417 ; ***************************** 418 ; *** DOS Function 32 *** 419 ; *** Get Requested DPB *** 420 ; ***************************** 421 ; 422 Public func32 423 func32: 0 000041C2 E8[0000] call set_retry_RF ; Valid to RETRY or FAIL 0 000041C5 B680 mov dh,80h ; set top bit - free space not needed 0 000041C7 E88A00 call fdos_DISKINFO ; and make the function call 0 000041CA 73E9 jnc f1B1C1F32_common ; exit using common code 428 ; jc fdos_DI_error ; check if error 429 ; cmp dosfat,FAT32 ; attempt to use on FAT32 drive? 430 ; jne f1B1C1F32_common ; exit using common code 431 ; mov ax,0ffh 432 fdos_DI_error: 0 000041CC E9[0000] jmp fcberror_exit ; exit thru FCB error 434 435 436 ; ***************************** 437 ; *** DOS Function 36 *** 438 ; *** Disk Free Space *** 439 ; ***************************** 440 ; 441 Public func36 442 func36: 0 000041CF E8[0000] call set_retry_RF ; Valid to RETRY or FAIL 0 000041D2 30F6 xor dh,dh ; clear out DH 0 000041D4 E87D00 call fdos_DISKINFO ; find out about drive 0 000041D7 730C jnc f36_OK ; CY set if we had a problem 0 000041D9 06 push es 0 000041DA 53 push bx 0 000041DB E8[0000] call error_exit ; generate a critical error 0 000041DE 5B pop bx 0 000041DF 07 pop es 0 000041E0 B8FFFF mov ax,0FFFFh ; Invalid Drive Return 0FFFFh 0 000041E3 726C jc f36_exit ; No Carry 454 f36_OK: 0 000041E5 268B4F02 mov cx,[es:DDSC_SECSIZE + bx] ; Get the Physical Sector Size 0 000041E9 E8[0000] call return_CX ; in bytes 457 0 000041EC 268B570D mov dx,[es:DDSC_NCLSTRS + bx] ; Convert the last cluster no 0 000041F0 833E[0000]00 cmp word [dosfat],FAT32 ; FAT32 file system? 0 000041F5 750E jne f36_OK20 ; no, then use the 16-bit value 0 000041F7 268B572F mov dx,word ptr [es:DDSC_BCLSTRS + bx] ; Convert the last cluster no 0 000041FB 26837F3100 cmp word ptr [es:DDSC_BCLSTRS+2 + bx],0 ; more than fits into 16-bit register? 0 00004200 7403 je f36_OK20 ; no, the value is exact 0 00004202 BAFFFF mov dx,0ffffh ; yes, so fake the value for maximum compatibility 465 f36_OK20: 0 00004205 4A dec dx ; returned in DDSC to maximum 0 00004206 E8[0000] call return_DX ; number of clusters 468 0 00004209 268B4F1F mov cx,[es:DDSC_FREE + bx] ; get number of free clusters 0 0000420D 31D2 xor dx,dx 0 0000420F 26837F0F00 cmp word [es:DDSC_NFATRECS + bx],0 ; could this be a FAT32 drive? 0 00004214 750F jne f36_OK25 ; nah, it must be FAT12/16 0 00004216 26807F178F cmp byte [es:DDSC_MEDIA + bx],8fh ; or is it a CD-ROM drive? 0 0000421B 7408 je f36_OK25 ; apparently it is one, so handle it like FAT12/16 0 0000421D 268B4F21 mov cx,word ptr [es:DDSC_BFREE + bx] ; get number of free clusters (32-bit) 0 00004221 268B5723 mov dx,word ptr [es:DDSC_BFREE+2 + bx] 477 f36_OK25: 0 00004225 31C0 xor ax,ax 0 00004227 268A4704 mov al,[es:DDSC_CLMSK + bx] ; get the sectors per cluster -1 0 0000422B 40 inc ax ; AX = sectors per cluster 481 %ifdef DELWATCH 0 0000422C 030E[0800] add cx,[FD_ADJUST] ; now add in DELWATCH adjustment 0 00004230 83D200 adc dx,0 484 %endif 485 f36_OK30: 0 00004233 83FA00 cmp dx,0 ; more than fits into 16-bit register? 0 00004236 7414 je f36_OK50 ; no, the value is exact 0 00004238 3C40 cmp al,64 ; cluster size already 64K? 0 0000423A 7308 jae f36_OK40 0 0000423C D0E0 shl al,1 ; cluster size * 2 0 0000423E D1EA shr dx,1 ; free clusters / 2 0 00004240 D1D9 rcr cx,1 0 00004242 EBEF jmp f36_OK30 ; try again 494 f36_OK40: 0 00004244 83FA00 cmp dx,0 ; more than fits into 16-bit register? 0 00004247 7403 je f36_OK50 ; no, the value is exact 0 00004249 B9FEFF mov cx,0fffeh ; yes, use a sane value for compatibility's sake 498 f36_OK50: 499 ; xor ax,ax 500 ; mov al,es:DDSC_CLMSK[bx] ; get the sectors per cluster -1 501 ; inc ax ; AX = sectors per cluster 502 0 0000424C 89CB mov bx,cx 0 0000424E E8[0000] call return_BX ; return free clusters 505 506 f36_exit: 0 00004251 E9[0000] jmp return_AX_CLC 508 509 public fdos_DISKINFO 510 fdos_DISKINFO: 511 ;------------- 512 ; Called by func1B, func1C, func1F, func32, func36 513 ; Even number functions have drive in DL 514 ; Odd numbered function use default drive (0) 515 ; 0 00004254 B84800 mov ax,FD_DISKINFO ; get information about drive 0 00004257 8706[0000] xchg ax,[FD_FUNC] ; while getting orginal function # 518 ; test al,1 ; is it func1B/func1F ? 0 0000425B 3C1B cmp al,1bh ; is it func1B/func1F ? 520 ; jz fdos_DI10 ; if so these use the default 0 0000425D 7404 je fdos_DI05 ; if so these use the default 0 0000425F 3C1F cmp al,1fh 0 00004261 7502 jne fdos_DI10 524 fdos_DI05: 0 00004263 30D2 xor dl,dl ; drive so zero DL 526 fdos_DI10: 0 00004265 8916[0200] mov [FD_DRIVE],dx ; drive in DX 0 00004269 E8[0000] call fdos_crit 0 0000426C C41E[0400] les bx,[FD_DPB] ; get the DPB pointer 0 00004270 C3 ret 531 532 ; ***************************** 533 ; *** DOS Function 2F *** 534 ; *** Get Disk Trans Adr *** 535 ; ***************************** 536 537 Public func2F 538 func2F: 0 00004271 C41E[0000] les bx,[dma_offset] ; current dma address 0 00004275 1E push ds 0 00004276 C53E[0000] lds di,[int21regs_ptr] 0 0000427A 8C4510 mov [reg_ES + di],es 0 0000427D 895D02 mov [reg_BX + di],bx 0 00004280 1F pop ds 0 00004281 C3 ret 546 547 548 ; ***************************** 549 ; *** DOS Function 41 *** 550 ; *** Delete File(s) *** 551 ; ***************************** 552 ; 553 Public func41 554 func41: 0 00004282 36833E[0000]00 cmp word [ss:remote_call],0 0 00004288 7502 jne fdos_common41 0 0000428A B106 mov cl,06h 558 559 ; ***************************** 560 ; *** DOS Function 39 *** 561 ; *** Create SubDirectory *** 562 ; ***************************** 563 ; 564 Public func39 565 func39: 566 567 ; ***************************** 568 ; *** DOS Function 3A *** 569 ; *** Delete SubDirectory *** 570 ; ***************************** 571 ; 572 Public func3A 573 func3A: 574 575 ; ***************************** 576 ; *** DOS Function 3B *** 577 ; *** Change SubDirectory *** 578 ; ***************************** 579 ; 580 Public func3B 581 func3B: 582 ; ***************************** 583 ; *** DOS Function 4E *** 584 ; *** Find First File *** 585 ; *** DOS Function 4F *** 586 ; *** Find Next File *** 587 ; ***************************** 588 ; 589 Public func4E 590 func4E: 591 Public func4F 592 func4F: 593 ; Func 4F has no parameters, but using the same routine saves code 594 595 fdos_common41: 0 0000428C E8[0000] call set_retry_RF ; Valid to RETRY or FAIL 597 ; jmp fdos_name 598 599 fdos_name: 0 0000428F 8916[0200] mov [FD_NAMEOFF],dx ; Initialise Pointer 0 00004293 8C06[0400] mov [FD_NAMESEG],es 0 00004297 890E[0800] mov [FD_ATTRIB],cx ; and attributes 0 0000429B C706[0A00]0000 mov word [FD_LFNSEARCH],0 ; do not use FAT+/LFN extensions 0 000042A1 E9[0000] jmp fdos_ax_crit 605 606 ; ***************************** 607 ; *** DOS Function 5B *** 608 ; *** Create New File *** 609 ; ***************************** 610 ; 611 Public func5B 612 func5B: 613 614 ; ***************************** 615 ; *** DOS Function 3C *** 616 ; *** Create a File *** 617 ; ***************************** 618 ; 619 Public func3C 620 func3C: 0 000042A4 E8[0000] call set_retry_RF ; Valid to RETRY or FAIL 0 000042A7 833E[0000]3C cmp word [FD_FUNC],MS_X_CREAT ; is it a standard create ? 0 000042AC 7406 je f3C_10 0 000042AE C706[0000]5100 mov word [FD_FUNC],FD_NEW ; no, create a new file 625 f3C_10: 0 000042B4 C706[0600]0200 mov word [FD_MODE],DHM_RW ; create as read/write 0 000042BA EBD3 jmp fdos_name ; go do it 628 629 ; ***************************** 630 ; *** DOS Function 3D *** 631 ; *** Open a File *** 632 ; ***************************** 633 ; 634 Public func3D 635 func3D: 0 000042BC E8[0000] call set_retry_RF ; Valid to RETRY or FAIL 0 000042BF 36833E[0000]00 cmp word [ss:remote_call],0 0 000042C5 7502 jne funcExtendedOpenCreate 0 000042C7 B106 mov cl,06h ; default search mode for local 640 ; jmp funcExtendedOpenCreate ; calls (remote it's in CL) 641 funcExtendedOpenCreate: 642 ; On Entry: 643 ; FD_FUNC = function to carry out 644 ; ES:DX -> name 645 ; AX = open mode 646 ; CX = file attributes 647 ; 0 000042C9 50 push ax 0 000042CA 2470 and al,DHM_SHAREMSK 0 000042CC 3C40 cmp al,DHM_DENY_NONE ; any funny share bits ? 0 000042CE 58 pop ax 0 000042CF 770D ja open_mode_err 0 000042D1 50 push ax 0 000042D2 240F and al,DHM_RWMSK 0 000042D4 3C02 cmp al,DHM_RW ; check RW bits are valid 0 000042D6 58 pop ax 0 000042D7 7705 ja open_mode_err 0 000042D9 A3[0600] mov [FD_MODE],ax ; Set Open Mode 0 000042DC EBB1 jmp fdos_name 660 661 open_mode_err: 0 000042DE B8F4FF mov ax,ED_ACC_CODE ; This is an illegal open mode 0 000042E1 E9[0000] jmp error_exit ; return an error 664 665 666 ; ***************************** 667 ; *** DOS Function 3F *** 668 ; *** Read from Handle *** 669 ; ***************************** 670 ; 671 Public func3F 672 func3F: 673 674 ; ***************************** 675 ; *** DOS Function 40 *** 676 ; *** Write to a Handle *** 677 ; ***************************** 678 ; 679 Public func40 680 func40: 0 000042E4 B038 mov al,OK_RIF ; Valid to RETRY,IGNORE or FAIL 0 000042E6 E8[0000] call set_retry 0 000042E9 8916[0400] mov [FD_BUFOFF],dx 0 000042ED 8C06[0600] mov [FD_BUFSEG],es 0 000042F1 890E[0800] mov [FD_COUNT],cx 0 000042F5 E84400 call fdos_handle 0 000042F8 8B16[0800] mov dx,[FD_COUNT] 0 000042FC 7316 jnc f40_10 ; no error, return # xfered 0 000042FE FF36[0200] push word [FD_HANDLE] 0 00004302 52 push dx ; an error, try critical error 0 00004303 E8[0000] call error_exit ; and if we get back here that 0 00004306 5A pop dx ; means we Fail/Ignore it 0 00004307 5B pop bx 0 00004308 720E jc f40_20 ; are we returning an error ? 0 0000430A 52 push dx ; no, we are ignoring it 0 0000430B 31C9 xor cx,cx ; CX:DX offset to skip 0 0000430D B80142 mov ax,(MS_X_LSEEK*256)+1 ; seek to current+offset 0 00004310 E8[0000] call dos_entry 0 00004313 5A pop dx ; finally return # we wanted 700 f40_10: ; to xfer 0 00004314 92 xchg ax,dx ; AX = return code 0 00004315 E9[0000] jmp return_AX_CLC 703 f40_20: 0 00004318 C3 ret 705 706 ; ***************************** 707 ; *** DOS Function 42 *** 708 ; *** Move R/W Pointer *** 709 ; ***************************** 710 ; 711 Public func42 712 func42: 0 00004319 E8[0000] call set_retry_RF ; Valid to RETRY or FAIL 0 0000431C 8916[0400] mov word ptr [FD_OFFSET+0],dx 0 00004320 890E[0600] mov word ptr [FD_OFFSET+2],cx 0 00004324 A3[0800] mov [FD_METHOD],ax 0 00004327 E81200 call fdos_handle 0 0000432A 720D jc f42_error ; Do not return the current 0 0000432C A1[0400] mov ax,word ptr [FD_OFFSET+0] ; file position if 0 0000432F 8B16[0600] mov dx,word ptr [FD_OFFSET+2] ; an error occurs 0 00004333 E8[0000] call return_DX 0 00004336 E9[0000] jmp return_AX_CLC 723 724 f42_error: 0 00004339 E9[0000] jmp error_exit 726 727 fdos_handle: 0 0000433C 891E[0200] mov [FD_HANDLE],bx 0 00004340 E9[0000] jmp fdos_crit 730 731 ; ***************************** 732 ; *** DOS Function 43 *** 733 ; *** Change File Mode *** 734 ; ***************************** 735 ; 736 ; Concurrent Password Support:- 737 ; 738 ; *WO* *GR* *OW* This is the format of the Password 739 ; P---$RWED$RWED$RWED mode word which is compatible with 740 ; the FlexOS F_PROTECT field. 741 ; *WO* World (Ignored) 742 ; *GR* Group (Ignored) The P flag is only used to designate 743 ; *OW* Owner (Used) that the password is being updated. 744 ; 745 Public func43 746 func43: 0 00004343 E8[0000] call set_retry_RF ; Valid to RETRY or FAIL 0 00004346 A3[0600] mov [FD_FLAG],ax ; Requested Attributes ignored 0 00004349 E843FF call fdos_name ; if flags are not being set 0 0000434C 72EB jc f42_error 0 0000434E E8[0000] call reload_registers ; get back AL 0 00004351 A881 test al,81h 0 00004353 7508 jnz f43_exit 0 00004355 8B0E[0800] mov cx,[FD_ATTRIB] 0 00004359 E8[0000] call return_CX ; Return Attribs/Password 0 0000435C 91 xchg ax,cx ; Also in AX 757 f43_exit: 0 0000435D E9[0000] jmp return_AX_CLC 759 760 ; ***************************** 761 ; *** DOS Function 46 *** 762 ; *** Force Dup Handle *** 763 ; ***************************** 764 ; 765 Public func46 766 func46: 0 00004360 87D9 xchg bx,cx ; destination handle in BX 0 00004362 B43E mov ah,MS_X_CLOSE ; try to close it but ignore 0 00004364 E8[0000] call dos_entry ; errors as it may be already 0 00004367 87D9 xchg bx,cx ; now fall thru to handle func 0 00004369 B446 mov ah,MS_X_DUP2 ; do do the duplicate 772 773 ; ***************************** 774 ; *** DOS Function 45 *** 775 ; *** Duplicate Handle *** 776 ; ***************************** 777 ; 778 Public func45 779 func45: 780 781 ; ***************************** 782 ; *** DOS Function 3E *** 783 ; *** Close a File *** 784 ; ***************************** 785 ; 786 Public func3E 787 func3E: 0 0000436B B008 mov al,OK_FAIL 0 0000436D E8[0000] call set_retry ; Valid to FAIL 0 00004370 890E[0400] mov [FD_NEWHND],cx ; (in case it's force dup) 791 ; jmp fdos_ax_handle 792 793 fdos_ax_handle: 0 00004374 891E[0200] mov [FD_HANDLE],bx 0 00004378 E9[0000] jmp fdos_ax_crit 796 797 ; ***************************** 798 ; *** DOS Function 5C *** 799 ; ***Lock/Unlock File Access*** 800 ; ***************************** 801 ; 802 Public func5C 803 func5C: 0 0000437B E8[0000] call set_retry_RF ; Valid to RETRY or FAIL 0 0000437E C706[0000]5200 mov word [FD_FUNC],FD_LOCK ; Lock/Unlock File 0 00004384 8916[0400] mov word ptr [FD_OFFSET+0],dx ; Lock Offset (LOW) 0 00004388 890E[0600] mov word ptr [FD_OFFSET+2],cx ; Lock Offset (HIGH) 0 0000438C 893E[0800] mov word ptr [FD_LENGTH+0],di ; Lock Length (LOW) 0 00004390 8936[0A00] mov word ptr [FD_LENGTH+2],si ; Lock Length (HIGH) 0 00004394 A3[0C00] mov [FD_LFLAG],ax ; Lock Type 0 00004397 EBDB jmp fdos_ax_handle 812 813 ; ***************************** 814 ; *** DOS Function 47 *** 815 ; *** Get Current Dir *** 816 ; ***************************** 817 ; 818 Public func47 819 func47: 0 00004399 E8[0000] call set_retry_RF ; Valid to RETRY or FAIL 0 0000439C 8936[0400] mov [FD_PATHOFF],si ; Initialise Pointer 0 000043A0 8C06[0600] mov [FD_PATHSEG],es 0 000043A4 92 xchg ax,dx ; drive in AL 0 000043A5 98 cbw ; make that AX 0 000043A6 A3[0200] mov [FD_DRIVE],ax 0 000043A9 E9[0000] jmp fdos_ax_crit ; return garbage in AH (SPJ bug) 827 828 ; ***************************** 829 ; *** DOS Function 53 *** 830 ; *** Build DPB from BPB *** 831 ; ***************************** 832 ; 833 ; This function takes the BPB at DS:SI and builds a DDSC at ES:BP 834 ; 835 Public func53 836 func53: 0 000043AC E8[0000] call set_retry_RF ; Valid to RETRY or FAIL 0 000043AF 8936[0200] mov [FD_BPBOFF],si ; Segment and Offset of BPB 0 000043B3 8C06[0400] mov [FD_BPBSEG],es 0 000043B7 892E[0600] mov [FD_DDSCOFF],bp ; Segment and Offset of DDSC 0 000043BB 890E[0A00] mov [FD_SIG1],cx ; signatures for extended function 0 000043BF 8916[0C00] mov [FD_SIG2],dx 0 000043C3 E8[0000] call reload_ES 0 000043C6 8C06[0800] mov [FD_DDSCSEG],es 0 000043CA E9[0000] jmp fdos_nocrit 846 ; 847 ; ***************************** 848 ; *** DOS Function 56 *** 849 ; *** Rename/Move a File *** 850 ; ***************************** 851 ; 852 Public func56 853 func56: 0 000043CD E8[0000] call set_retry_RF ; Valid to RETRY or FAIL 0 000043D0 893E[0A00] mov [FD_NNAMEOFF],di ; New FileName 0 000043D4 06 push es 0 000043D5 E8[0000] call reload_ES ; callers ES:DI 0 000043D8 8C06[0C00] mov [FD_NNAMESEG],es ; point to new filename 0 000043DC 07 pop es 0 000043DD 8916[0200] mov [FD_ONAMEOFF],dx ; Old FileName 0 000043E1 8C06[0400] mov [FD_ONAMESEG],es 0 000043E5 36833E[0000]00 cmp word [ss:remote_call],0 0 000043EB 7502 jne func56_10 0 000043ED B117 mov cl,17h 865 func56_10: 0 000043EF 890E[0800] mov [FD_ATTRIB],cx 0 000043F3 E9[0000] jmp fdos_crit 868 869 ; ***************************** 870 ; *** DOS Function 57 *** 871 ; *** Get/Set File Time *** 872 ; ***************************** 873 ; 874 Public func57 875 func57: 0 000043F6 E8[0000] call set_retry_RF ; Valid to RETRY or FAIL 0 000043F9 8916[0600] mov [FD_DATE],dx 0 000043FD 890E[0800] mov [FD_TIME],cx 0 00004401 A3[0400] mov [FD_SFLAG],ax 0 00004404 3C01 cmp al,1 ; allow get/set only 0 00004406 B8FFFF mov ax,ED_FUNCTION ; all else fails horribly 0 00004409 771B ja f57_error 0 0000440B E82EFF call fdos_handle 0 0000440E 7216 jc f57_error 0 00004410 E8[0000] call reload_registers 0 00004413 84C0 test al,al 0 00004415 750E jnz f57_exit 0 00004417 8B0E[0800] mov cx,[FD_TIME] 0 0000441B E8[0000] call return_CX ; return TIME in CX 0 0000441E 8B16[0600] mov dx,[FD_DATE] 0 00004422 E9[0000] jmp return_DX ; and DATE in DX 892 893 f57_exit: 0 00004425 C3 ret 895 896 f57_error: 0 00004426 E9[0000] jmp error_exit 898 899 ; ***************************** 900 ; *** DOS Function 5A *** 901 ; *** Create Unique File *** 902 ; ***************************** 903 ; 904 Public func5A 905 func5A: 0 00004429 B8FBFF mov ax,ED_ACCESS ; assume we will have an error 0 0000442C F7C1D800 test cx,DA_FIXED ; because of silly attributes 0 00004430 753C jnz func5A_40 ; did we ? 0 00004432 89D6 mov si,dx ; find end of pathname 0 00004434 31C0 xor ax,ax ; no previous char 911 func5A_10: 0 00004436 93 xchg ax,bx ; BL = previous char 0 00004437 26AC es lodsb ; get next char 0 00004439 84C0 test al,al ; is it the end of the string? 0 0000443B 7408 jz func5A_20 0 0000443D E8[0000] call dbcs_lead ; is it a KANJI char? 0 00004440 75F4 jnz func5A_10 0 00004442 46 inc si ; skip 2nd char of pair 0 00004443 EBF1 jmp func5A_10 920 func5A_20: 0 00004445 4E dec si ; SI -> NUL 0 00004446 80FB5C cmp bl,'\' ; was last char a '\' ? 0 00004449 740A je func5A_30 0 0000444B 80FB2F cmp bl,'/' ; (or a '/' for unix freaks) 0 0000444E 7405 je func5A_30 0 00004450 26C6045C mov byte ptr [es:si],'\' ; append a '\' to name 0 00004454 46 inc si 928 func5A_30: 929 ; Here ES:DX -> start of name, ES:SI -> position to append ,0 930 ; CX = attribute for file. 931 ; We generate a unique name based upon the time and date - if this already 932 ; exists we keep retrying knowing the number of files is finite and we must 933 ; succeed eventually 0 00004455 51 push cx 0 00004456 52 push dx 0 00004457 56 push si ; append a unique'ish name 0 00004458 E81900 call func5A_append_unique_name 0 0000445B 5E pop si 0 0000445C 5A pop dx 0 0000445D 59 pop cx 0 0000445E B45B mov ah,MS_X_MKNEW ; try to create unique file 0 00004460 E8[0000] call dos_entry 0 00004463 730C jnc func5A_50 ; exit if we succeeded 0 00004465 26C60400 mov byte ptr [es:si],0 ; else forget extention 0 00004469 83F8B0 cmp ax,ED_EXISTS ; we only retry if it already exists 0 0000446C 74E7 je func5A_30 947 func5A_40: 0 0000446E E9[0000] jmp error_exit ; return error to caller 949 func5A_50: 0 00004471 E9[0000] jmp return_AX_CLC ; return handle to caller 951 952 func5A_append_unique_name: 953 ;------------------------- 954 ; On Entry: 955 ; ES:DX -> start of name 956 ; ES:SI -> position to append ,0 957 ; CX = attribute for file. 958 ; On Exit: 959 ; None 960 ; 961 ; We append a unique 8 character filename to this based upon the current 962 ; date/time. 0 00004474 56 push si 0 00004475 B80D12 mov ax,120dh 0 00004478 CD2F int 2fh ; get date/time in AX & DX 0 0000447A 5F pop di 0 0000447B 0306[0000] add ax,[unique_name_seed] ; randomise the date otherwise we would 0 0000447F FF06[0000] inc word [unique_name_seed] ; have one second wait between names 0 00004483 E80800 call func5A_app_AX ; store 4 ascii bytes 0 00004486 92 xchg ax,dx ; was DX = time 0 00004487 E80400 call func5A_app_AX ; store 4 ascii bytes 0 0000448A 31C0 xor ax,ax 0 0000448C AA stosb ; and a terminating NUL 0 0000448D C3 ret 975 976 func5A_app_AX: 977 ; On Entry AX = word, ES:DI -> string 978 ; Store 4 ASCII chars at ES:DI, based upon value in AX 0 0000448E E80000 call func5A_app_AL ; do low byte, falling thru to do high 980 func5A_app_AL: 0 00004491 E80000 call func5A_app_NIB ; low nibble, falling thru for high 982 func5A_app_NIB: 0 00004494 50 push ax 0 00004495 240F and al,0fh ; mask out a nibble 0 00004497 0441 add al,'A' ; make it ASCII character 0 00004499 AA stosb ; plant the string 0 0000449A 58 pop ax 0 0000449B B104 mov cl,4 0 0000449D D3E8 shr ax,cl ; shift nibble 0 0000449F C3 ret 991 992 993 ; ***************************** 994 ; *** DOS Function 60 *** 995 ; ***Perform Name Processing*** 996 ; ***************************** 997 ; 998 ; DS:SI point to a source string which contains a relative path 999 ; specification ES:DI points to a buffer which is at least 80 1000 ; bytes longer than the source string. 1001 ; 1002 ; The carry flag is set and AX contains an error code if the 1003 ; source string is mal formed. This function is used by the 1004 ; Ryan-McFarland COBOL compiler. 1005 ; 1006 Public func60 1007 func60: 0 000044A0 E8[0000] call set_retry_RF ; Valid to RETRY or FAIL 0 000044A3 C706[0000]5500 mov word [FD_FUNC],FD_EXPAND ; Expand a relative Path 0 000044A9 8936[0200] mov [FD_ONAMEOFF],si ; Initialise Source Pointer 0 000044AD 8C06[0400] mov [FD_ONAMESEG],es 0 000044B1 893E[0A00] mov [FD_NNAMEOFF],di ; Initialise Destination 0 000044B5 E8[0000] call reload_ES ; pointer 0 000044B8 8C06[0C00] mov [FD_NNAMESEG],es 0 000044BC E9[0000] jmp fdos_crit 1016 1017 ; ***************************** 1018 ; *** DOS Function 67 *** 1019 ; *** Set/Handle Count *** 1020 ; ***************************** 1021 ; 1022 ; We impose a minimum of 20 handles regardless of what the caller 1023 ; requests. If the request is <=20 we use the default handle table in 1024 ; the PSP, else we allocate a memory block for the new table. 1025 ; If the old handle table was in a memory block (ie. zero offset) we 1026 ; will free that block up afterwards. 1027 ; When shrinking the handle count the error ED_HANDLE will be given if 1028 ; open files would have been lost. 1029 ; 1030 1031 Public func67 1032 func67: 0 000044BF 1E push ds 0 000044C0 8E1E[0000] mov ds,[current_psp] ; DS -> current PSP blk 0 000044C4 83FB14 cmp bx,20 ; force to minimum value of 20 0 000044C7 7303 jae f67_10 0 000044C9 BB1400 mov bx,20 ; never have less than 20 handles 1038 f67_10: 1039 0 000044CC 8B0E3200 mov cx,[PSP_XFNMAX] ; we have this many handles 0 000044D0 29D9 sub cx,bx ; are we growing ? 0 000044D2 760F jbe f67_20 ; if shrinking make sure none open 0 000044D4 C43E3400 les di,[PSP_XFTPTR] ; point to existing handle table 0 000044D8 8D39 lea di,[di+bx] ; point to 1st handle we will lose 0 000044DA B0FF mov al,0FFh ; they must all be closed 0 000044DC F3AE repe scasb ; or we fail 0 000044DE B8FCFF mov ax,ED_HANDLE ; fail if we are in danger of losing 0 000044E1 7551 jne f67_error ; open handles 1049 f67_20: 1050 0 000044E3 53 push bx ; save # of handles wanted 0 000044E4 1E push ds 0 000044E5 07 pop es 0 000044E6 BF1800 mov di,offset PSP_XFT ; ES:DI -> new handle table 0 000044E9 83FB14 cmp bx,20 ; if we are setting to the 0 000044EC 7410 je f67_30 ; default size 0 000044EE 83C30F add bx,15 ; calculate memory required 0 000044F1 B104 mov cl,4 0 000044F3 D3EB shr bx,cl ; num of paragraphs required 0 000044F5 31FF xor di,di ; offset will be zero 0 000044F7 B448 mov ah,MS_M_ALLOC ; allocate the memory 0 000044F9 E8[0000] call dos_entry 0 000044FC 8EC0 mov es,ax ; ES:DI -> new handle table 1064 f67_30: 0 000044FE 5B pop bx ; BX = # handles wanted 0 000044FF 7233 jc f67_error ; ES:DI -> new handle table 1067 0 00004501 89D9 mov cx,bx ; CX = new # handles 0 00004503 870E3200 xchg cx,[PSP_XFNMAX] ; Update the Handle Count 1070 0 00004507 89FE mov si,di ; Update the Table Offset 0 00004509 87363400 xchg si,[PSP_XFTOFF] 0 0000450D 8CC0 mov ax,es 0 0000450F 87063600 xchg ax,[PSP_XFTSEG] ; Update the Table Segment 0 00004513 8ED8 mov ds,ax ; DS:SI -> old handle table 1076 ; ES:DI -> new handle table 1077 ; CX = # old handles to copy 1078 ; BX = # new handles desired 1079 0 00004515 29CB sub bx,cx ; BX = # extra "closed" handles 0 00004517 7304 jae f67_40 ; negative if we are shrinking 0 00004519 01D9 add cx,bx ; CX = # handles we inherit 0 0000451B 31DB xor bx,bx ; BX = no extra "closed" handles 1084 f67_40: 1085 0 0000451D 56 push si ; save offset old handle table 0 0000451E F3A4 rep movsb ; Copy the existing Handles 0 00004520 5E pop si ; SI = offset old handle table 1089 0 00004521 B0FF mov al,0FFh ; AL = unused handle 0 00004523 89D9 mov cx,bx ; mark extra handles as unused 0 00004525 F3AA rep stosb ; mark as unused 1093 0 00004527 85F6 test si,si ; do we have memory to free ? 0 00004529 7505 jnz f67_50 0 0000452B B449 mov ah,MS_M_FREE 0 0000452D E8[0000] call dos_entry ; free up old handle table DMD 1098 f67_50: 0 00004530 1F pop ds 0 00004531 E9[0000] jmp return_AX_CLC ; clear carry on return 1101 1102 f67_error: 0 00004534 1F pop ds ; restore DS 0 00004535 E9[0000] jmp error_exit ; and return error AX to caller 1105 1106 ; ***************************** 1107 ; *** DOS Function 68 *** 1108 ; *** Commit File *** 1109 ; ***************************** 1110 ; 1111 Public func68 1112 func68: 0 00004538 E8[0000] call set_retry_RF ; Valid to RETRY or FAIL 0 0000453B C706[0000]5000 mov word [FD_FUNC],FD_COMMIT ; Close a File Handle 0 00004541 E9F8FD jmp fdos_handle 1116 1117 1118 ; ***************************** 1119 ; *** DOS Function 6C *** 1120 ; *** Extended Open *** 1121 ; ***************************** 1122 ; 1123 1124 Public func6C 1125 func6C: 0 00004544 B018 mov al,OK_RF ; Valid to RETRY or FAIL 0 00004546 F6C720 test bh,20h ; should we allow critical errors ? 0 00004549 7402 jz f6C10 0 0000454B 0C40 or al,NO_CRIT_ERRORS ; no, so remember that 1130 f6C10: 0 0000454D E8[0000] call set_retry 0 00004550 B8FFFF mov ax,ED_FUNCTION ; assume an illegal action code 0 00004553 F7C2ECFE test dx,~ 0113h ; now check for sensible bits 0 00004557 755D jnz f6C_error 0 00004559 42 inc dx 0 0000455A F6C204 test dl,4 ; also reject bits 0-3 = 3 0 0000455D 7557 jnz f6C_error 0 0000455F 4A dec dx 1139 0 00004560 96 xchg ax,si ; ES:AX -> name 0 00004561 92 xchg ax,dx ; AX = action, ES:DX -> name 0 00004562 93 xchg ax,bx ; AX = open mode, BX = action 1143 0 00004563 F6C310 test bl,010h ; should we create if not there ? 0 00004566 7411 jz f6C_open ; no, skip the attempt at make new 1146 0 00004568 80E460 and ah,(DHM_COMMIT+DHM_NOCRIT)/100h 0 0000456B C706[0000]5100 mov word [FD_FUNC],FD_NEW ; create only if not there 0 00004571 E855FD call funcExtendedOpenCreate ; try to open/create the file 1150 0 00004574 B90200 mov cx,2 ; CX = file created 0 00004577 7333 jnc f6C_exit ; return this if we succeeded 1153 1154 f6C_open: 0 00004579 E8[0000] call reload_registers ; all registers as per entry 0 0000457C 96 xchg ax,si ; ES:AX -> name 0 0000457D 92 xchg ax,dx ; AX = action, ES:DX -> name 0 0000457E 93 xchg ax,bx ; AX = open mode, BX = action 0 0000457F 53 push bx ; save action 0 00004580 80E460 and ah,(DHM_COMMIT+DHM_NOCRIT)/100h 0 00004583 C706[0000]3D00 mov word [FD_FUNC],MS_X_OPEN ; try an open an existing file 0 00004589 E83DFD call funcExtendedOpenCreate 0 0000458C 5B pop bx ; recover action 0 0000458D 7227 jc f6C_error ; return error if we can't open file 1165 0 0000458F B90100 mov cx,1 ; CX = file opened 0 00004592 F6C301 test bl,001h ; should we open if it exists ? 0 00004595 7515 jnz f6C_exit ; yes, return the handle 1169 0 00004597 93 xchg ax,bx ; BX = handle, AX = action 0 00004598 A802 test al,002h ; should we replace the file ? 0 0000459A B8B0FF mov ax,ED_EXISTS ; if not close and return error 0 0000459D 7410 jz f6C_close_on_error 0 0000459F B440 mov ah,MS_X_WRITE 0 000045A1 31C9 xor cx,cx ; write zero bytes to truncate file 0 000045A3 E8[0000] call dos_entry 0 000045A6 7207 jc f6C_close_on_error ; on error AX = error code, return it 0 000045A8 93 xchg ax,bx ; AX = handle 0 000045A9 B90300 mov cx,3 ; CX = file replaced 1180 f6C_exit: 0 000045AC E9[0000] jmp return_CX ; return CX to caller 1182 1183 f6C_close_on_error: 1184 ; File exits, but open should be failed (error code in AX) 0 000045AF 50 push ax 0 000045B0 B43E mov ah,MS_X_CLOSE 0 000045B2 E8[0000] call dos_entry ; close that file 0 000045B5 58 pop ax 1189 f6C_error: 0 000045B6 E9[0000] jmp error_exit ; generate critical error 1191 1192 PCM_CODE ends 1193 === Switch to base=00C180h -> "PCMODE_DATA" 1194 section PCMODE_DATA public align=2 class=DATA 1195 extrn current_psp:word 1196 extrn current_dsk:byte 1197 extrn dma_offset:word 1198 extrn dma_segment:word 1199 extrn int21regs_ptr:dword 1200 extrn last_drv:byte 1201 extrn remote_call:word 1202 %ifdef DELWATCH 1203 extrn fdos_stub:dword 1204 %endif 1205 PCMODE_DATA ends 1206 === Switch to base=00C180h -> "GLOBAL_DATA" 1207 section GLOBAL_DATA public align=2 class=DATA 1208 ; When creating unique files we use the date/time to make the name. 1209 ; We add this seed value to "randomise" things, INCing on failure so the next 1210 ; attempt usually succeeds. 1211 0 000012BA 0000 unique_name_seed dw 0 ; so we don't have to wait 1 second 1213 1214 GLOBAL_DATA ends 1215 1216 end === Trace listing source: drdos/bin/ioctl.lst 1 ; File : $IOCTL.ASM$ 2 ; 3 ; Description : 4 ; 5 ; Original Author : DIGITAL RESEARCH 6 ; 7 ; Last Edited By : $CALDERA$ 8 ; 9 ;-----------------------------------------------------------------------; 10 ; Copyright Work of Caldera, Inc. All Rights Reserved. 11 ; 12 ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, 13 ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. 14 ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES 15 ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF 16 ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO 17 ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE 18 ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE 19 ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, 20 ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, 21 ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, 22 ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF 23 ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT 24 ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND 25 ; CIVIL LIABILITY. 26 ;-----------------------------------------------------------------------; 27 ; 28 ; *** Current Edit History *** 29 ; *** End of Current Edit History *** 30 ; $Log: $ 31 ; IOCTL.A86 1.17 94/11/28 15:42:19 32 ; f440B now does not modify net_retry if DX=0 33 ; IOCTL.A86 1.16 93/11/08 19:15:18 34 ; SETVER to subversion 0xFF disabled int 21/4452 35 ; IOCTL.A86 1.15 93/07/26 18:16:16 36 ; add some code which disables drdos check if app is SETVER'd 37 ; leave said code disabled unless required 38 ; IOCTL.A86 1.14 93/07/22 19:29:54 39 ; get/set serial number now the correct way round 40 ; IOCTL.A86 1.11 93/06/17 22:14:34 41 ; support for ioctl 10/11 query ioctl support 42 ; ENDLOG 43 ; 44 ; 7 Nov 87 Removal of development flags 45 ; 17 Dec 87 Return "Single device Supported" for IOCTL sub-functions 46 ; 0Eh and 0Fh. 47 ; 24 Feb 88 Return 1060h from IOCTL sub-function 51h under DOS PLUS 48 ; instead of the Concurrent DOS OS version. 49 ; 24 Feb 88 Correct Generic IOCTL function and prevent the generation 50 ; of critical errors. 51 ; 24 May 88 sub-function 53h returns the address of the INT24 handler 52 ; for the command processor. 53 ; 01 Jun 88 Add sub-function 4454 to support setting the default password 54 ; 03 Nov 88 Add History Buffer Sub-Command f4456 for DOSPLUS 55 ; 02 Feb 89 Add code page switching sub-function 0Ch 56 ; 19 Feb 89 Support Sub-Command f4457 to control SHARE 57 ; 15 Mar 89 Do not generate critical errors from 4402 and 4403. 58 ; 18 Apr 89 Sub-function 53 only suported for Concurrect DOS 59 ; 19 Apr 89 Don't clobber error code on 440D and 440E (pc-cache) 60 ; 31 May 89 New function f4458 to return pointer to private data. 61 ; 31 May 89 f440B sets up DOS internal data 62 ; 15 Jun 89 Don't throw away inheritance bit when masking Share Mode Flags 63 ; 11 Oct 89 f4407/07 set AX on return, not just AL 64 ; 26 Oct 89 for a few bytes more... 65 ; 18 Jan 90 HILOAD interface added onto f4457 66 ; 25 Jan 90 INT21/4458 returns a pointer to IDLE_DATA in ES:AX 67 ; 13 Jan 90 private_data exported in CDOS for DEBUG systems 68 ; 27 Feb 90 4459 provides Int21 function that does Int224 calls 69 ; 7 Mar 90 Convert to register preserved function calls 70 ; 14 Mar 90 No critical error generated in IOCTL functions 71 ; 3 May 90 stop forcing ioctl 4403/3/4/5 errors to ED_ACCESS 72 ; 4 Jun 90 445A provides user group support on CDOS 73 ; 3 jun 92 Add 4456/2+3 to examine history state, toggle history enable 74 ; 30 jul 92 HILOAD now uses official memory strategy calls 75 ; 76 77 group PCMCODE PCM_CODE PCM_RODATA 78 group PCMDATA PCMODE_DATA FDOS_DSEG 79 80 ASSUME DS:PCMDATA 81 82 [list -] 92 === Switch to base=000000h -> "PCM_CODE" 93 section PCM_CODE public align=1 class=CODE 94 extrn os_version:word 95 extrn patch_version:word 96 97 extrn invalid_function:near 98 extrn error_ret:near 99 extrn fdos_nocrit:near 100 extrn fdos_crit:near 101 extrn fdos_ax_crit:near 102 extrn return_AX_CLC:near 103 extrn return_DX:near 104 extrn return_DSBX_as_ESBX:near 105 extrn set_retry_RF:near 106 extrn patch_version:word 107 108 109 ; ***************************** 110 ; *** DOS Function 69 *** 111 ; *** set/get serial num *** 112 ; ***************************** 113 ; 114 Public func69 115 func69: 0 000045B9 E8[0000] call set_retry_RF ; Prepare for an FDOS function 0 000045BC C706[0000]4400 mov word [FD_FUNC],MS_X_IOCTL 0 000045C2 B96608 mov cx,866h ; assume a get serial num 0 000045C5 3C01 cmp al,1 ; check for 0/1 0 000045C7 B00D mov al,0Dh ; ready for ioctl 0D 0 000045C9 7209 jb func44common ; go ahead with get serial num 0 000045CB B146 mov cl,46h ; maybe it's a set 0 000045CD 7405 je func44common ; go ahead with set serial num 124 ; jmp invalid_function ; ah well, it's an invalid one 0 000045CF EB35 jmp f44_30 126 127 ; ***************************** 128 ; *** DOS Function 44 *** 129 ; *** I/O Control *** 130 ; ***************************** 131 ; 132 Public func44 133 func44: 0 000045D1 E8[0000] call set_retry_RF ; Prepare for an FDOS function 135 func44common: 0 000045D4 A3[0400] mov [FD_IOCTLFUNC],ax ; save subfunction for FDOS 0 000045D7 C606[0000]16 mov byte [ioctlRH],22 ; assume RH will be wanted 0 000045DC C606[0D00]00 mov byte [ioctlRH+13],0 ; init len and media byte 0 000045E1 8916[0E00] mov word ptr [ioctlRH+14],dx ; point at buffer segment 0 000045E5 8C06[1000] mov word ptr [ioctlRH+16],es 0 000045E9 890E[1200] mov word ptr [ioctlRH+18],cx ; the Byte Count 0 000045ED 83F812 cmp ax,dosf44_ftl ; Check for a valid PC-DOS 0 000045F0 730B jae f44_20 ; sub-functions 144 f44_10: 0 000045F2 96 xchg ax,si 0 000045F3 D1E6 shl si,1 0 000045F5 2E8BB4[0000] mov si,[cs:func44_ft + si] 0 000045FA 96 xchg ax,si 0 000045FB FFE0 jmp ax 150 f44_20: 0 000045FD 2C40 sub al,52h-dosf44_ftl ; adjust to our base of 52h 0 000045FF 7205 jc f44_30 ; bail out if too low 0 00004601 83F819 cmp ax,ourf44_ftl ; is it too high ? 0 00004604 72EC jb f44_10 155 f44_30: 0 00004606 E9[0000] jmp invalid_function 157 158 ; *********************************************** 159 ; *** Sub Function 00 - Get Device Info *** 160 ; *********************************************** 161 f4400: 0 00004609 E89300 call fdos_handle ; execute the function 0 0000460C 89C2 mov dx,ax ; return in DX too 164 return_AX_and_DX: 0 0000460E E8[0000] call return_DX ; return to caller in DX 0 00004611 E9[0000] jmp return_AX_CLC ; return AX too 167 168 ; *********************************************** 169 ; *** Sub Function 01 - Set Device Info *** 170 ; *** Sub Function 06 - Get Input Status *** 171 ; *** Sub Function 07 - Get Output Status *** 172 ; *********************************************** 173 f4401: 174 f4406: 175 f4407: 0 00004614 E88800 call fdos_handle ; Execute the Function 0 00004617 E9[0000] jmp return_AX_CLC 178 179 ; ************************************************ 180 ; *** Sub Function 04 - Read Blk Device *** 181 ; *** Sub Function 05 - Write Blk Device *** 182 ; *** Sub Function 11 - Query ioctl Blk *** 183 ; ************************************************ 184 ; 185 f4404: 186 f4405: 187 f4411: 0 0000461A 30FF xor bh,bh ; BX = drive number 189 190 ; ************************************************ 191 ; *** Sub Function 02 - Read Character Dev *** 192 ; *** Sub Function 03 - Write Character Dev *** 193 ; *** Sub Function 10 - Query ioctl Char *** 194 ; ************************************************ 195 ; 196 f4402: 197 f4403: 198 f4410: 0 0000461C BA8000 mov dx,DA_QUERY ; assume we will query support 0 0000461F B019 mov al,CMD_QUERY_IOCTL ; and be ready to go 0 00004621 8B0E[0400] mov cx,[FD_IOCTLFUNC] ; re-read the function number 0 00004625 F6C110 test cl,10h ; is it function 10 of 11? 0 00004628 750C jnz f44ioctl ; yes, we are ready 0 0000462A BA0040 mov dx,DA_IOCTL ; no, we actually want to do it 0 0000462D B003 mov al,CMD_INPUT_IOCTL ; even functions are input 0 0000462F F6C101 test cl,1 ; test for input functions 0 00004632 7402 jz f44ioctl 0 00004634 B00C mov al,CMD_OUTPUT_IOCTL ; odd functions are output 209 f44ioctl: 0 00004636 8916[0600] mov [FD_IOCTLSTAT],dx ; this device driver support is required 0 0000463A A2[0200] mov [ioctlRH+2],al ; this is the function 0 0000463D E85F00 call fdos_handle ; Execute the Function 0 00004640 A1[1200] mov ax,word ptr [ioctlRH+18] ; return # xfered 0 00004643 E9[0000] jmp return_AX_CLC 215 216 ; ***************************** 217 ; *** Sub Function 09 *** 218 ; *** Networked Media *** 219 ; ***************************** 220 ; 221 f4409: 0 00004646 E85400 call fdos_drive ; Execute the Function 0 00004649 89C2 mov dx,ax ; Get the Return Information 0 0000464B B80003 mov ax,0300h 0 0000464E EBBE jmp return_AX_and_DX 226 227 ; ***************************** 228 ; *** Sub Function 0A *** 229 ; *** Networked Handle *** 230 ; ***************************** 231 ; 232 f440A: 0 00004650 E84C00 call fdos_handle ; Execute the Function 0 00004653 89C2 mov dx,ax ; Get the Return Information 0 00004655 E9[0000] jmp return_DX ; and return in DX 236 237 ; ***************************** 238 ; *** Sub Function 0B *** 239 ; *** Update Share Retry *** 240 ; ***************************** 241 ; 242 ; dos_CX [1] Number of times to execute the delay loop 243 ; which consists of xor cx,cx ! loop $ 244 ; 245 ; dos_DX [3] Number of times to retry 246 ; 247 ; 248 f440B: 0 00004658 890E[0000] mov [net_delay],cx 0 0000465C 85D2 test dx,dx 251 f440B_10 equ f440b_10 ; NASM port label 0 0000465E 7404 jz f440B_10 0 00004660 8916[0000] mov [net_retry],dx 254 f440b_10: 0 00004664 C3 ret 256 257 ; ***************************** 258 ; *** Sub Function 0D *** 259 ; *** Device Driver Req *** 260 ; ***************************** 261 ; 262 f440D: 0 00004665 30FF xor bh,bh 264 ; jmp f440C 265 266 ; ***************************** 267 ; *** Sub Function 0C *** 268 ; *** Code Page Switching *** 269 ; ***************************** 270 ; 271 f440C: 0 00004667 C706[0600]4000 mov word [FD_IOCTLSTAT],DA_GETSET ; device driver support required 0 0000466D 891E[0200] mov [FD_HANDLE],bx ; Save the Handle Number 0 00004671 C606[0000]17 mov byte [ioctlRH],23 ; different RH length 0 00004676 C606[0200]13 mov byte [ioctlRH+2],CMD_GENERIC_IOCTL 0 0000467B 86CD xchg cl,ch ; swap minor/major functions 0 0000467D 890E[0D00] mov word ptr [ioctlRH+13],cx ; and store in request header 0 00004681 8936[0F00] mov word ptr [ioctlRH+15],si 0 00004685 893E[1100] mov word ptr [ioctlRH+17],di 0 00004689 8916[1300] mov word ptr [ioctlRH+19],dx ; point at buffer segment 0 0000468D 8C06[1500] mov word ptr [ioctlRH+21],es 0 00004691 E8[0000] call fdos_ax_crit ; Execute the Function and 0 00004694 7215 jc fdos_error ; return all error codes 0 00004696 C3 ret 285 286 ; *********************************************** 287 ; *** Sub Function 08 - Removable Media *** 288 ; *** Sub Function 0E - Get Logical Drive *** 289 ; *** Sub Function 0F - Set Logical Drive *** 290 ; *********************************************** 291 ; 292 f4408: 293 f440E: 294 f440F: 0 00004697 E80300 call fdos_drive ; Execute the Function 0 0000469A E9[0000] jmp return_AX_CLC ; return result in AX 297 298 299 fdos_drive: 300 ;---------- 0 0000469D 30FF xor bh,bh ; BX = the drive number 302 fdos_handle: 303 ;---------- 0 0000469F 891E[0200] mov [FD_HANDLE],bx 0 000046A3 E8[0000] call fdos_crit ; then execute the FDOS 0 000046A6 7306 jnc fdos_OK ; exit on Error 0 000046A8 83C402 add sp,2 ; discard near return address 308 fdos_error: 0 000046AB E9[0000] jmp error_ret ; and return the error 310 fdos_OK: 0 000046AE A1[0600] mov ax,[FD_IOCTLSTAT] ; get the return information 0 000046B1 C3 ret 313 314 ; ***************************** 315 ; *** CCP/M Extension *** 316 ; *** Sub Function 52 *** 317 ; *** Return CCP/M Version *** 318 ; ***************************** 319 ; 320 f4452: 0 000046B2 8E06[0000] mov es,[current_psp] ; version is kept in the PSP 0 000046B6 26813E400000FF cmp word [es:PSP_VERSION],0FF00h ; sub-version of 255 ? 0 000046BD 730F jae f4452_10 ; then say we ain't DRDOS 0 000046BF 2EA1[0000] mov ax,[cs:os_version] ; Get OS ver number 0 000046C3 2E8B16[0000] mov dx,[cs:patch_version] 0 000046C8 E8[0000] call return_DX ; return in DX 0 000046CB E9[0000] jmp return_AX_CLC ; return in AX 328 f4452_10: 0 000046CE E9[0000] jmp invalid_function 330 331 %ifdef PASSWORD 332 333 ; ***************************** 334 ; *** CCP/M Extension *** 335 ; *** Sub Function 54 *** 336 ; *** Set Default PASSWORD *** 337 ; ***************************** 338 ; 339 f4454: 0 000046D1 C706[0400]0B00 mov word [FD_IOCTLFUNC],0Bh ; save subfunction for FDOS 0 000046D7 E9[0000] jmp fdos_nocrit ; Execute the Function 342 343 %endif 344 345 346 ; ***************************** 347 ; *** CCP/M Extension *** 348 ; *** Sub Function 56 *** 349 ; *** History Buffer Cntrl *** 350 ; ***************************** 351 ; 352 ; This function changes the default history buffer used for func0A: 353 ; 354 ; On Entry: 355 ; DL = 0 -> Standard Process Buffer 356 ; DL = 1 -> Command.com history Buffer 357 ; DL = 2 -> Toggle history enable/disable 358 ; DL = 3 -> Get current state of history buffers 359 ; DL = 4 -> Toggle insert mode 360 ; 361 ; On Exit: 362 ; AL = previous history state (Bit 0 set if history on) 363 ; Bit 0 -> set if history enabled 364 ; Bit 1 -> set if insert enabled 365 ; Bit 7 -> set if command history buffer 366 ; 367 f4456: 0 000046DA A1[0000] mov ax,[cle_state] ; Get the current History Status 0 000046DD 80FA02 cmp dl,2 ; are we disabling/enabling ? 0 000046E0 7215 jb f4456_10 ; below, switch buffers 0 000046E2 7409 je f4456_05 ; yes, try and do it 0 000046E4 80FA04 cmp dl,4 ; toggle insert state ? 0 000046E7 7521 jne f4456_20 ; no, return existing state 0 000046E9 3402 xor al,RLF_INS ; toggle insert state 0 000046EB EB1D jmp f4456_20 ; set and return prev state 376 377 f4456_05: 0 000046ED B101 mov cl,RLF_ENHANCED ; we are interested in enhancements 0 000046EF 840E[0000] test [@hist_flg],cl ; only if history possible 0 000046F3 7415 jz f4456_20 ; just return existing state 0 000046F5 30C8 xor al,cl ; invert current setting 382 ; and fall thru' to enable/disable 383 ; standard buffer (never called 384 ; by COMMAND...) 385 f4456_10: 0 000046F7 0C80 or al,RLF_INROOT ; assume we are in the root 387 %if IDLE_DETECT 0 000046F9 830E[0000]01 or word [idle_flags],IDLE_COMMAND 389 %endif 0 000046FE F6C201 test dl,1 ; Get new state and mask bit 0 00004701 7507 jnz f4456_20 0 00004703 247F and al,~ RLF_INROOT ; we are in application buffer 393 %if IDLE_DETECT 0 00004705 8326[0000]FE and word [idle_flags],~ IDLE_COMMAND 395 %endif 396 f4456_20: 0 0000470A 8706[0000] xchg ax,[cle_state] ; set state, returning old state 0 0000470E C3 ret 399 400 401 ; ***************************** 402 ; *** CCP/M Extension *** 403 ; *** Sub Function 58 *** 404 ; *** Private Data Func *** 405 ; ***************************** 406 ; 407 ; On Exit ES:BX points to our DRDOS private data. 408 ; ES:AX points to the IDLE Data Area 409 410 f4458: 0 0000470F BB[0000] mov bx,offset @private_data 0 00004712 E8[0000] call return_DSBX_as_ESBX ; return ES:BX pointing to private data 0 00004715 B8[0000] mov ax,offset idle_data 0 00004718 E9[0000] jmp return_AX_CLC 415 416 PCM_CODE ends 417 418 === Switch to base=000000h -> "PCM_RODATA" 419 section PCM_RODATA public align=2 class=CODE 420 ; 421 ; PCDOS Sub-Functions Only 422 ; 0 0000B956 [5000] func44_ft dw f4400 0 0000B958 [5B00] dw f4401 0 0000B95A [6300] dw f4402 0 0000B95C [6300] dw f4403 0 0000B95E [6100] dw f4404 0 0000B960 [6100] dw f4405 0 0000B962 [5B00] dw f4406 0 0000B964 [5B00] dw f4407 0 0000B966 [DE00] dw f4408 0 0000B968 [8D00] dw f4409 0 0000B96A [9700] dw f440A 0 0000B96C [9F00] dw f440B 0 0000B96E [AE00] dw f440C 0 0000B970 [AC00] dw f440D 0 0000B972 [DE00] dw f440E 0 0000B974 [DE00] dw f440F 0 0000B976 [6300] dw f4410 0 0000B978 [6100] dw f4411 441 dosf44_ftl equ (offset $ - offset func44_ft)/2 442 ; 443 ; CCP/M Sub-Functions Only 444 ; 0 0000B97A [F900] dw f4452 ; 4452 OS version no 0 0000B97C [0000] dw invalid_function ; 4453 Invalid Function 447 %ifdef PASSWORD 0 0000B97E [1801] dw f4454 ; 4454 set default password 449 %else 450 dw invalid_function ; 4454 was set default password 451 %endif 0 0000B980 [0000] dw invalid_function ; 4455 Invalid Function 0 0000B982 [2101] dw f4456 ; 4456 history buffer support 0 0000B984 [0000] dw invalid_function ; 4457 was share enable/disable 0 0000B986 [5601] dw f4458 ; 4458 pointer to private data 456 457 ourf44_ftl equ (offset $ - offset func44_ft)/2 458 459 PCM_RODATA ends 460 461 === Switch to base=00C180h -> "PCMODE_DATA" 462 section PCMODE_DATA public align=2 class=DATA 463 464 extrn net_delay:word, net_retry:word 465 extrn @hist_flg:byte 466 extrn @private_data:byte 467 %if IDLE_DETECT 468 extrn idle_data:word 469 extrn idle_flags:word 470 %endif 471 extrn cle_state:word 472 extrn ioctlRH:byte 473 extrn dos_version:word 474 extrn current_psp:word 475 476 PCMODE_DATA ends 477 478 end === Trace listing source: drdos/bin/misc.lst 1 ; File : $MISC.ASM$ 2 ; 3 ; Description : 4 ; 5 ; Original Author : DIGITAL RESEARCH 6 ; 7 ; Last Edited By : $CALDERA$ 8 ; 9 ;-----------------------------------------------------------------------; 10 ; Copyright Work of Caldera, Inc. All Rights Reserved. 11 ; 12 ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, 13 ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. 14 ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES 15 ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF 16 ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO 17 ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE 18 ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE 19 ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, 20 ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, 21 ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, 22 ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF 23 ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT 24 ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND 25 ; CIVIL LIABILITY. 26 ;-----------------------------------------------------------------------; 27 ; 28 ; *** Current Edit History *** 29 ; *** End of Current Edit History *** 30 ; $Log$ 31 ; MISC.A86 1.29 94/11/30 14:40:17 32 ; fixed error return for function 6602 33 ; MISC.A86 1.28 94/07/13 15:31:04 34 ; Pass name to share on Int21/5D02 (close file by name) 35 ; MISC.A86 1.27 93/11/29 14:18:16 36 ; Fix bug in get extended country info if not current country 37 ; MISC.A86 1.25 93/11/19 17:00:14 38 ; If 21/38 get country info fails for current codepage, try any codepage 39 ; MISC.A86 1.24 93/11/16 15:57:08 40 ; int 21/5D06 clears CY flag 41 ; MISC.A86 1.23 93/10/21 19:31:16 42 ; Move Int 21/5D03+5D04 support (close all files by machine/psp) into share 43 ; MISC.A86 1.22 93/10/18 17:41:45 44 ; fix for >255 open files (PNW Server) 45 ; MISC.A86 1.21 93/09/03 20:28:57 46 ; Add intl/dbcs support for int 21/6523 (query yes/no char) 47 ; MISC.A86 1.20 93/07/26 20:42:13 48 ; Seperate int21/3306 49 ; MISC.A86 1.12 93/03/05 18:12:33 50 ; Fix DS corruption for NLSFUNC calls 51 ; ENDLOG 52 ; 53 54 group PCMDATA PCMODE_DATA FDOS_DSEG GLOBAL_DATA PCMODE_DSIZE PCMODE_CODE 55 group PCMCODE PCM_CODE PCM_RODATA 56 57 ASSUME DS:PCMDATA 58 59 VALID_SIG equ 0EDC1h 60 61 [list -] 73 74 NLSFUNC equ TRUE 75 76 ; === Switch to base=00C180h -> "GLOBAL_DATA" 77 section GLOBAL_DATA public align=2 class=DATA 78 extrn default_country:byte 79 extrn Ucasetbl:word 80 extrn FileUcasetbl:word 81 extrn FileCharstbl:word 82 extrn Collatingtbl:word 83 extrn DBCS_tbl:word 84 extrn NoYesChars:byte 85 extrn info1_len:abs 86 extrn info2_len:abs 87 extrn info4_len:abs 88 extrn info5_len:abs 89 extrn info6_len:abs 90 extrn info7_len:abs 91 extrn dos_version:word 92 extrn country_filename:byte 93 GLOBAL_DATA ends 94 === Switch to base=00C180h -> "PCMODE_CODE" 95 section PCMODE_CODE public align=2 class=DATA 96 extrn xlat_xlat:word 97 PCMODE_CODE ends 98 === Switch to base=000000h -> "PCM_CODE" 99 section PCM_CODE public align=1 class=CODE 100 extrn dbcs_lead:near 101 extrn device_write:near ; Write to a Character Device 102 extrn device_read:near ; Read from a Character Device 103 extrn dos_entry:near 104 extrn error_exit:near 105 extrn error_ret:near 106 extrn func5F_common:near 107 extrn get_dseg:near 108 extrn valid_drive:near 109 extrn ifn2dhndl:near 110 extrn int21_func:near 111 extrn invalid_function:near 112 extrn patch_version:word 113 extrn reload_registers:near 114 extrn reload_ES:near 115 extrn return_AX_CLC:near 116 extrn return_BX:near 117 extrn return_CX:near 118 extrn return_DX:near 119 extrn toupper:near 120 121 ; 122 ; ***************************** 123 ; *** DOS Function 34 *** 124 ; *** Get The Indos Flag *** 125 ; ***************************** 126 Public func34 127 func34: 0 0000471B BB[0000] mov bx,offset indos_flag 129 ; jmp return_DSBX_as_ESBX ; return ES:BX -> indos flag 130 131 Public return_DSBX_as_ESBX 132 133 return_DSBX_as_ESBX: 134 ;------------------- 135 ; On Entry: 136 ; DS:BX to be returned to caller in ES:BX 137 ; On Exit: 138 ; ES/DI trashed 139 ; 0 0000471E 36C43E[0000] les di,[ss:int21regs_ptr] 0 00004723 268C5D10 mov [es:reg_ES + di],ds 0 00004727 26895D02 mov [es:reg_BX + di],bx 0 0000472B C3 ret 144 145 146 ; 147 ; ***************************** 148 ; *** DOS Function 52 *** 149 ; *** Get Internal Data *** 150 ; ***************************** 151 ; 152 ; 153 Public func52 154 func52: 0 0000472C BB[0000] mov bx,offset func52_data 0 0000472F EBED jmp return_DSBX_as_ESBX ; return ES:BX -> internal data 157 158 ; 159 ; ***************************** 160 ; *** DOS Function 5D *** 161 ; *** Private DOS Func *** 162 ; ***************************** 163 ; 164 ; 165 Public func5D 166 func5D: 0 00004731 3C07 cmp al,7 168 f5d_05 equ f5D_05 ; NASM port label 0 00004733 731B jae f5d_05 0 00004735 89D6 mov si,dx ; ES:SI -> callers structure 0 00004737 268B5C14 mov bx,word ptr [es:20 + si] 0 0000473B 36891E[0000] mov [ss:owning_psp],bx ; update PSP from there 0 00004740 803E[0000]26 cmp byte [WindowsHandleCheck],26h 0 00004745 7509 jne f5D_05 ; check if Windows is running 0 00004747 268B5C12 mov bx,word ptr [es:18 + si] 0 0000474B 36891E[0000] mov [ss:machine_id],bx ; no, update machine_id 177 f5D_05: 0 00004750 98 cbw ; zero AH for valid functions 0 00004751 93 xchg ax,bx ; sub function in BX 180 0 00004752 83FB0B cmp bx,func5D_ftl ; Assume Illegal Subfunction 0 00004755 7203 jb f5D_10 ; check that it is a valid 0 00004757 BB0B00 mov bx,func5D_ftl ; subfunction 184 f5D_10: 0 0000475A D1E3 shl bx,1 0 0000475C 2EFFB7[0000] push word [cs:func5D_ft + bx] ; save function address 0 00004761 D1EB shr bx,1 0 00004763 93 xchg ax,bx ; restore BX 0 00004764 C3 ret ; go to function 190 191 f5D_msnet: 0 00004765 B82511 mov ax,I2F_REDIR_5D ; magic number to redirect 0 00004768 E9[0000] jmp func5F_common ; calls to extentions 194 ; 195 ; 196 ; The registers for some of the following sub-functions are passed 197 ; in the following structure. 198 ; 199 labelsize RDC_AX, word, es:00 + di ; User AX 200 labelsize RDC_BX, word, es:02 + di ; User BX 201 labelsize RDC_CX, word, es:04 + di ; User CX 202 labelsize RDC_DX, word, es:06 + di ; User DX 203 labelsize RDC_SI, word, es:08 + di ; User SI 204 labelsize RDC_DI, word, es:10 + di ; User DI 205 labelsize RDC_DS, word, es:12 + di ; User DS 206 labelsize RDC_ES, word, es:14 + di ; User ES 207 labelsize RDC_RES, word, es:16 + di ; Remote Machine ID (High Word) 208 labelsize RDC_UID, word, es:18 + di ; Remote Machine ID (Low Word) 209 labelsize RDC_PID, word, es:20 + di ; Process ID 210 ; 211 ; ***************************** 212 ; *** DOS Function 5D00 *** 213 ; *** Remote DOS Call *** 214 ; ***************************** 215 ; 216 ; 217 f5D00: 0 0000476B C706[0000]FF00 mov word [remote_call],0ffh ; set remote op flag 0 00004771 06 push es 0 00004772 C43E[0000] les di,[int21regs_ptr] ; stack image the copy registers 0 00004776 1F pop ds 0 00004777 B90600 mov cx,6 0 0000477A F3A5 rep movsw ; Copy AX, BX, CX, DX, SI, DI 0 0000477C 47 inc di 0 0000477D 47 inc di ; Skip BP in the destination 0 0000477E A5 movsw 0 0000477F A5 movsw ; finally copy DS and ES 0 00004780 16 push ss 0 00004781 1F pop ds ; DS -> PCMDSEG 0 00004782 E8[0000] call reload_registers ; load up the new registers 0 00004785 E9[0000] jmp int21_func ; then execute that function 232 233 ; ***************************** 234 ; *** DOS Function 5D01 *** 235 ; *** Commit all files *** 236 ; ***************************** 237 ; 238 f5D01: 239 ;----- 240 ; We are being asked to commit all files to disk 241 ; By pretending to be FCB's we force use of IFN's, and we commit all possible 242 ; files in the range 0-255, ignoring errors from unopened handles. 243 ; 0 00004788 C706[0000]0080 mov word [remote_call],DHM_FCB ; pretend to be FCB, forces use of IFN 0 0000478E 31DB xor bx,bx ; start with handle zero 246 f5D01_10: 0 00004790 B468 mov ah,MS_X_COMMIT 0 00004792 E8[0000] call dos_entry ; commit this file 0 00004795 43 inc bx ; onto next candidate 0 00004796 81FBFF00 cmp bx,0FFh ; runout yet ? 0 0000479A 72F4 jb f5D01_10 ; 0 0000479C C3 ret 253 254 255 ; ***************************** 256 ; *** DOS Function 5D02 *** 257 ; *** Close file by name *** 258 ; ***************************** 259 ; 260 f5D02: 261 ;----- 262 ; Close file by name. We do a search first to find out about the file. 263 ; As long as it's local we call share with the directory cluster/index 264 ; to close it if it's open. 265 ; 0 0000479D 89D7 mov di,dx ; ES:DI -> register block 0 0000479F 268B5506 mov dx,[RDC_DX] 0 000047A3 268E450C mov es,[RDC_DS] ; ES:DX -> filename to close 0 000047A7 FF36[0000] push word [dma_offset] 0 000047AB FF36[0000] push word [dma_segment] 0 000047AF C706[0000][0000] mov word [dma_offset],offset fcb_search_buf 0 000047B5 8C1E[0000] mov [dma_segment],ds 0 000047B9 B90700 mov cx,DA_RO+DA_SYSTEM+DA_HIDDEN 0 000047BC B44E mov ah,MS_X_FIRST ; look for this file 0 000047BE E8[0000] call dos_entry ; to get dir entry info 0 000047C1 8F06[0000] pop word [dma_segment] 0 000047C5 8F06[0000] pop word [dma_offset] 0 000047C9 7223 jc f5Dret 0 000047CB A0[0000] mov al,[fcb_search_buf] ; get drive # 0 000047CE 84C0 test al,al ; reject networked drives 0 000047D0 781C js f5Dret 0 000047D2 48 dec ax ; make drive zero based 0 000047D3 8B0E[0D00] mov cx,word ptr [fcb_search_buf+0Dh] 284 ; CX = directory count 0 000047D7 8B16[0E00] mov dx,word ptr [fcb_search_buf+0Eh] 286 ; DX = parent directory cluster 0 000047DB 8D1E[0100] lea bx,[fcb_search_buf+1] ; DS:BX -> name 0 000047DF BF2000 mov di,S_CLOSE_IF_OPEN 289 ; jmp f5D_common 290 f5D_common: 0 000047E2 FF1E[0000] call far [lock_tables] ; protect SHARE with a critical section 0 000047E6 FF9D[0000] call far [share_stub + di] 0 000047EA FF1E[0000] call far [unlock_tables] ; safe again 294 f5Dret: 0 000047EE C3 ret 296 297 ; ***************************** 298 ; *** DOS Function 5D03 *** 299 ; *** Close files by machine*** 300 ; ***************************** 301 ; 302 ; ***************************** 303 ; *** DOS Function 5D04 *** 304 ; *** Close by Machine/PSP *** 305 ; ***************************** 306 f5D03: 307 f5D04: 308 ;----- 309 ; Close all files for given PSP 310 ; 0 000047EF BF2C00 mov di,S_CLOSE_FILES 0 000047F2 EBEE jmp f5D_common 313 314 315 ; ***************************** 316 ; *** DOS Function 5D05 *** 317 ; ***************************** 318 ; 319 f5D05: 320 ; On Entry: 321 ; RDC.BX = Share File # to look to 322 ; RDC.CX = Share Record # to look for 323 ; On Exit: 324 ; AX = DOSHNDL Attribute Word 325 ; BX = machine ID 326 ; CX = locked blocks count 327 ; ES:DI -> buffer containing full pathname 328 ; 329 ; 0 000047F4 FF1E[0000] call far [lock_tables] ; protect SHARE with a critical section 0 000047F8 FF1E[2800] call far [share_stub+S_GET_LIST_ENTRY] 0 000047FC FF1E[0000] call far [unlock_tables] ; safe again 0 00004800 73EC jnc f5Dret ; just return if it went OK 0 00004802 E9[0000] jmp error_ret ; else return error code in AX 335 336 337 ; ***************************** 338 ; *** DOS Function 5D06 *** 339 ; *** Get Internal Data *** 340 ; ***************************** 341 ; 342 f5D06: 0 00004805 B9[0000] mov cx,offset swap_indos ; Calculate Size of Swap 0 00004808 81E9[0000] sub cx,offset internal_data ; Swap INDOS Array 0 0000480C E8[0000] call return_CX ; CX = Swap Indos length 0 0000480F BA[0000] mov dx,offset swap_always ; Calculate Size of Swap 0 00004812 81EA[0000] sub dx,offset internal_data ; Swap ALWAYS Array 0 00004816 E8[0000] call return_DX ; DX = Swap Always length 0 00004819 BE[0000] mov si,offset internal_data 0 0000481C E86B01 call return_DSSI 0 0000481F B8065D mov ax,5D06h 0 00004822 E9[0000] jmp return_AX_CLC 353 354 355 ; 356 ; ***************************** 357 ; *** DOS Function 5D0A *** 358 ; ***Set Extended Error Info*** 359 ; ***************************** 360 ; 361 f5D0A: 0 00004825 89D6 mov si,dx ; ES:SI -> parameter block 0 00004827 26AD es lodsw 0 00004829 A3[0000] mov [error_code],ax ; copy the appropriate fields 0 0000482C 26AD es lodsw 0 0000482E 8826[0000] mov [error_class],ah 0 00004832 A2[0000] mov [error_action],al 0 00004835 26AD es lodsw 0 00004837 8826[0000] mov [error_locus],ah 0 0000483B 83C604 add si,2*2 ; skip to device 0 0000483E 26AD es lodsw 0 00004840 A3[0000] mov [error_dev],ax 0 00004843 26AD es lodsw 0 00004845 A3[0200] mov [error_dev+2],ax 0 00004848 31C0 xor ax,ax ; return AL=0 0 0000484A C3 ret 377 ; 378 ; ***************************** 379 ; *** Get switch character *** 380 ; ***************************** 381 ; 382 ; 383 Public func37 384 func37: 0 0000484B 3C01 cmp al,1 0 0000484D 720D jb f37_getswitch ; Get the current Switch Character 0 0000484F 7412 je f37_setswitch ; Set the Switch Character 0 00004851 3C03 cmp al,3 0 00004853 7406 je f37_s03 ; Sub-Func 03 Return Unchanged 0 00004855 B2FF mov dl,0ffh 0 00004857 7207 jb f37_return_DX ; Sub-Func 02 Return DL == 0FFh 0 00004859 B0FF mov al,0FFh ; else invalid sub-function 393 f37_s03: 0 0000485B C3 ret 395 396 f37_getswitch: 0 0000485C 8A16[0000] mov dl,[switch_char] 398 f37_return_DX: 0 00004860 E9[0000] jmp return_DX ; return current setting in DX 400 401 f37_setswitch: 0 00004863 8816[0000] mov [switch_char],dl 0 00004867 C3 ret 404 405 ;************************************************** 406 ;************************************************** 407 ;*** *** 408 ;*** Miscellaneous Isolated Functions *** 409 ;*** *** 410 ;************************************************** 411 ;************************************************** 412 ; 413 ; ***************************** 414 ; *** DOS Function 30 *** 415 ; *** Get Version Number *** 416 ; ***************************** 417 418 Public func30 419 func30: 0 00004868 88C1 mov cl,al ; save value of AL 0 0000486A 8E06[0000] mov es,[current_psp] ; version is kept in the PSP 0 0000486E 26A14000 mov ax,[es:PSP_VERSION] 423 ReturnVersionNumber: 0 00004872 31DB xor bx,bx ; zero BX 0 00004874 80F901 cmp cl,1 ; version flag requested? 0 00004877 7402 je f30_10 ; yes, then return 0 427 ; cmp ax,dos_version ; has the version number been faked? 428 ; je f30_10 ; yes, then report OEM code 0 (PC DOS) 0 00004879 B7EE mov bh,0eeh ; OEM = EEh (DR DOS) 430 f30_10: 0 0000487B 31C9 xor cx,cx ; zero CX 0 0000487D E8[0000] call return_BX 0 00004880 E8[0000] call return_CX 0 00004883 E9[0000] jmp return_AX_CLC 435 436 ; 437 ; ***************************** 438 ; *** DOS Function 33 *** 439 ; *** Get/Set Cntl-Break *** 440 ; ***************************** 441 Public func33 442 443 ; WARNING - called on USER stack 444 445 func33: 0 00004886 3CFF cmp al, 0FFh ; is it function 33FFh ? 0 00004888 7552 jne f33_XX ; no, jump --> 0 0000488A E84800 call f33_FF ; yes 449 %if SVARDOS 450 %include "svarver.mac" 451 db KERNEL_VER_STR 452 %else 453 %include "version.mac" 1 <1> %imacro comment 0-*.nolist 2 <1> %endmacro 3 <1> 4 <1> %ifndef SHORTVERSION 5 <1> %undef shortversion 6 <1> %define if comment 7 <1> %define ifdef comment 8 <1> %define else comment 9 <1> %define endif comment 10 <1> %include "version.inc" 1 <2> 0 0000488D 456E68616E63656420 db 'Enhanced DR-DOS 7.01.08 WIP (2024 August)' 0 00004896 44522D444F5320372E 0 0000489F 30312E303820574950 0 000048A8 202832303234204175 0 000048B1 6775737429 3 <2> ifdef shortversion 4 <2> else 0 000048B6 206261736564206F6E db ' based on Caldera OpenDOS 7.01' 0 000048BF 2043616C6465726120 0 000048C8 4F70656E444F532037 0 000048D1 2E3031 6 <2> endif 11 <1> %undef if 12 <1> %undef ifdef 13 <1> %undef else 14 <1> %undef endif 15 <1> %else 16 <1> %define shortversion 1 17 <1> %macro if 1.nolist 18 <1> %define db comment 19 <1> %endmacro 20 <1> %macro ifdef 1.nolist 21 <1> %define db comment 22 <1> %endmacro 23 <1> %macro else 0.nolist 24 <1> %define db comment 25 <1> %endmacro 26 <1> %macro endif 0.nolist 27 <1> %undef db 28 <1> %endmacro 29 <1> %include "version.inc" 30 <1> %undef db 31 <1> %unmacro if 1.nolist 32 <1> %unmacro ifdef 1.nolist 33 <1> %unmacro else 0.nolist 34 <1> %unmacro endif 0.nolist 35 <1> %endif 454 %endif 0 000048D4 00 db 0 456 0 000048D5 8F4600 f33_FF: pop word [reg_AX + bp] ; dx:ax - hidden DOS string 0 000048D8 8C4E06 mov [reg_DX + bp], cs 0 000048DB C3 ret 460 461 f33_XX: 0 000048DC 3C02 cmp al,2 ; range check subfunction 0 000048DE 7611 jbe f33_10 0 000048E0 8A16[0000] mov dl,[bootDrv] ; assume we want boot drive 0 000048E4 3C05 cmp al,5 ; did we ? 0 000048E6 741A je f33_30 0 000048E8 3C06 cmp al,6 ; get true version ? 0 000048EA 741A je f33_60 0 000048EC C64600FF mov byte [reg_AL + bp],0FFh ; return AL = FF 0 000048F0 C3 ret ; Illegal function request 471 f33_10: 0 000048F1 80E201 and dl,01h ; force a valid value 0 000048F4 3C01 cmp al,1 ; check for get or set 0 000048F6 7304 jae f33_20 0 000048F8 8A16[0000] mov dl,[break_flag] ; it's a get, so use existing setting 476 f33_20: 0 000048FC 8616[0000] xchg dl,[break_flag] ; replace current setting 0 00004900 7403 je f33_40 479 f33_30: 0 00004902 885606 mov [reg_DL + bp],dl ; return setting in DL 481 f33_40: 0 00004905 C3 ret 483 484 f33_60: 0 00004906 8E06[0000] mov es,[current_psp] 0 0000490A 26A14000 mov ax,[es:PSP_VERSION] ; reported version for current program 0 0000490E 3B06[0000] cmp ax,[dos_version] ; has this been faked with SETVER? 0 00004912 894602 mov [reg_BX + bp],ax 0 00004915 7506 jne f33_61 ; yes, then fake the true version, too 0 00004917 A1[FEFF] mov ax,[dos_version-2] ; if not, then honestly return true version number 0 0000491A 894602 mov [reg_BX + bp],ax 492 f33_61: 0 0000491D 2EA1[0000] mov ax,[cs:patch_version] 0 00004921 894606 mov [reg_DX + bp],ax ; return revision+HMA 0 00004924 C3 ret 496 497 498 ; 499 ; ***************************** 500 ; *** DOS Function 25 *** 501 ; *** Set Interrupt Vector *** 502 ; ***************************** 503 ; 504 505 ; WARNING - use no stack as device drivers have called us re-entrantly 506 507 Public func25 508 func25: 0 00004925 8CC3 mov bx,es ; is really dos_DS - save for later 0 00004927 31FF xor di,di ; replace with the values in dos_DS:DX 0 00004929 8EC7 mov es,di ; es -> zero segment 0 0000492B 30E4 xor ah,ah ; the interrupt number 0 0000492D 89C7 mov di,ax ; 0:di -> vector 0 0000492F D1E7 shl di,1 0 00004931 D1E7 shl di,1 ; 4 bytes per vector 516 0 00004933 FA cli 0 00004934 92 xchg ax,dx ; Get New Offset 0 00004935 AB stosw ; and Save 0 00004936 93 xchg ax,bx ; Get New Segment 0 00004937 AB stosw ; and Save 0 00004938 FB sti 0 00004939 92 xchg ax,dx ; recover entry AL to (preserve it) 0 0000493A C3 ret 525 526 ; ***************************** 527 ; *** DOS Function 35 *** 528 ; *** Get Interrupt Vector *** 529 ; ***************************** 530 531 ; WARNING - use no stack as device drivers have called us re-entrantly 532 533 Public func35 534 func35: 0 0000493B 31DB xor bx,bx 0 0000493D 8EDB mov ds,bx ; DS:0 -> vector table 0 0000493F 88C3 mov bl,al ; BX = the interrupt number 0 00004941 D1E3 shl bx,1 0 00004943 D1E3 shl bx,1 ; 4 bytes per vector 0 00004945 C51F lds bx,[bx] ; DS:BX -> vector 0 00004947 36C43E[0000] les di,[ss:int21regs_ptr] 0 0000494C 26895D02 mov [es:reg_BX + di],bx 0 00004950 268C5D10 mov [es:reg_ES + di],ds 0 00004954 E9[0000] jmp get_dseg ; restore DS for return 545 546 ;PC-DOS Verify and Break Flags Support 547 ; 548 ; ***************************** 549 ; *** DOS Function 2E *** 550 ; *** Set/Reset Verify *** 551 ; ***************************** 552 Public func2E 553 func2E: 0 00004957 2401 and al,1 ; only use bottom bit 0 00004959 A2[0000] mov [verify_flag],al ; store for use later 0 0000495C C3 ret 557 558 ; ***************************** 559 ; *** DOS Function 54 *** 560 ; *** Get Verify Setting *** 561 ; ***************************** 562 Public func54 563 func54: 0 0000495D A0[0000] mov al,[verify_flag] ; return verify flag 0 00004960 C3 ret 566 567 ; ***************************** 568 ; *** DOS Function 63 *** 569 ; *** Get Lead Byte Table *** 570 ; ***************************** 571 ; 572 573 574 Public func63 575 func63: 0 00004961 3C01 cmp al, 1 ; subfunction #? 0 00004963 7222 jb f63_get_tbl ; subfunction 0 0 00004965 7416 je f63_set_flg ; subfunction 1 0 00004967 3C02 cmp al, 2 ; subfunction 2? 0 00004969 7406 je f63_get_flg ; yes 581 0 0000496B B8FFFF mov ax, ED_FUNCTION ; invalid subfunction number 0 0000496E E9[0000] jmp error_exit ; so quit 584 585 586 f63_get_flg: 587 ; Get the current state of the DOS interim character console flag. 588 ; If this flag is set int 21h functions 07h, 08h, 0Bh, 0Ch are supposed 589 ; to return "interim character information" which I assume is incomplete 590 ; characters. (In languages like Korean a given double byte character 591 ; may be built by the user entering several keystrokes which form 592 ; incomplete characters.) 0 00004971 8E06[0000] mov es, [current_psp] 0 00004975 268A163C00 mov dl, [es:PSP_RIC] ; Return Interim Character flag 0 0000497A E9[0000] jmp return_DX ; flag returned in dl 596 597 598 f63_set_flg: 599 ; Set the current state of the DOS interim character console flag. 600 ; dos_DL = 0 - clear flag, dos_DL = 1 - set flag 0 0000497D 8E06[0000] mov es, [current_psp] 0 00004981 2688163C00 mov [es:PSP_RIC], dl ; record flag 0 00004986 C3 ret 604 605 606 f63_get_tbl: 607 ; Get the current DBCS table address. 0 00004987 BE[0200] mov si,offset DBCS_tbl+2; skip the table size entry 609 ; jmp return_DSSI 610 611 return_DSSI: 612 ;----------- 613 ; On Entry: 614 ; DS:SI to be returned to caller 615 ; On Exit: 616 ; AX preserved 617 ; 0 0000498A 36C43E[0000] les di,[ss:int21regs_ptr] 0 0000498F 268C5D0E mov [es:reg_DS + di],ds 0 00004993 26897508 mov [es:reg_SI + di],si 0 00004997 C3 ret 622 623 ; 624 ; ***************************** 625 ; *** DOS Function 29 *** 626 ; *** Parse String *** 627 ; ***************************** 628 Public func29 629 func29: 630 ; 631 ; Entry: 632 ; DS:SI -> line to parse 633 ; ES:DI -> resulting fcb 634 ; Exit: 635 ; DS:SI -> terminating delimeter past parsed filename 636 ; ES:DI -> filled in fcb (Affects 16 bytes: DnnnnnnnnTTT0000) 637 ; 0 00004998 1E push ds 0 00004999 06 push es 0 0000499A E8[0000] call reload_ES 0 0000499D 1F pop ds 0 0000499E E80700 call parse 0 000049A1 E8E6FF call return_DSSI ; return result of parse 0 000049A4 1F pop ds 0 000049A5 88F0 mov al,dh ; return result in AL 0 000049A7 C3 ret 647 648 ;----- 649 parse: ; parse DOS filename delimited by TAB,SPACE,or .,+:;=|"/\[]<> or ctrl 650 ;----- 651 ; Entry: 652 ; DS:SI -> line to parse 653 ; ES:DI -> fcb to parse into 654 ; AL == bit options: 655 ; Bit 0 == 1: scan off leading delimiters 656 ; Bit 1 == 1: change drive only if specified 657 ; Bit 2 == 1: change name " " " 658 ; Bit 3 == 1: change type " " " 659 ; Exit: 660 ; DS:SI -> terminating delimeter past parsed filename 661 ; ES:DI -> filled in fcb (Affects 16 bytes: DnnnnnnnnTTT0000) 662 ; DH == 1 if wild, 0FFh if the drive is invalid, 0 otherwise 663 ; 0 000049A8 57 push di ; (<--keep DI last on stack) 665 0 000049A9 FC cld ; ChSh 0 000049AA 31D2 xor dx,dx ; DH = default return value (0) 0 000049AC 86C2 xchg al,dl ; put flags into DL, AL = 0 669 0 000049AE B90100 mov cx,1 0 000049B1 F6C202 test dl,0010b ; should we initialize drive? 0 000049B4 E86000 call nz_store_al ; do conditional store 673 0 000049B7 B020 mov al,' ' ; use spaces for filename & typ 675 0 000049B9 B108 mov cl,8 0 000049BB F6C204 test dl,0100b ; should we initialize the name? 0 000049BE E85600 call nz_store_al 679 0 000049C1 B103 mov cl,3 0 000049C3 F6C208 test dl,1000b ; should we initialize the typ? 0 000049C6 E84E00 call nz_store_al 683 0 000049C9 31C0 xor ax,ax ; zero-out the 4 post-typ bytes 0 000049CB AB stosw 0 000049CC AB stosw 687 0 000049CD 5F pop di 0 000049CE 57 push di ; restore DI to start of FCB 690 691 deblank_loop: 0 000049CF AC lodsb ; grab char 0 000049D0 3C20 cmp al,' ' ; is it a blank? 0 000049D2 74FB je deblank_loop ; Y: keep looping 0 000049D4 3C09 cmp al,'I'-'@' ; is it a tab? 0 000049D6 74F7 je deblank_loop ; Y: keep looping 697 0 000049D8 F6C201 test dl,0001b ; skip-delimiter-bit set? 0 000049DB 7409 jz parse_drive ; N: go start parsing 700 701 skip_delim_loop: 0 000049DD E87800 call check_delimiters ; check AL for delimiterness 0 000049E0 7232 jb parse_dec_ret ; found terminator, dec SI & leave 0 000049E2 88F2 mov dl,dh ; flag no-more-delimiter-skip (DL = 0) 0 000049E4 74E9 je deblank_loop ; found separator, go deblank after it 706 707 parse_drive: 0 000049E6 4E dec si 0 000049E7 807C013A cmp byte ptr [1 + si],':' ; is the drive specified? 0 000049EB 7516 jne parse_name 0 000049ED AD lodsw ; get drive, junk colon 0 000049EE 245F and al,01011111b ; upper case it 0 000049F0 2C40 sub al,'@' ; AL = 1-relative drive # 0 000049F2 50 push ax 0 000049F3 1E push ds ; Save the drive code and call 0 000049F4 E8[0000] call get_dseg ; Restore our Data Segment 0 000049F7 E8[0000] call valid_drive ; routine to validate drive ZR == OK 0 000049FA 1F pop ds 0 000049FB 58 pop ax ; Restore drive code and User DS 0 000049FC 7402 jz parse_d10 0 000049FE FECE dec dh ; flag drive error (0FFh) 722 parse_d10: 0 00004A00 268805 mov [es:di],al ; insert drive in fcb 724 725 parse_name: 0 00004A03 47 inc di ; DI -> fname 0 00004A04 B90800 mov cx,8 0 00004A07 E81400 call parse_item ; parse an up-to 8 char filename 0 00004A0A 80FA2E cmp dl,'.' ; was the delimeter a '.'? 0 00004A0D 7505 jne parse_dec_ret ; N: the parse is complete 731 0 00004A0F B103 mov cl,3 0 00004A11 E80A00 call parse_item ; parse an up-to 3 char filetype 734 parse_dec_ret: 0 00004A14 4E dec si ; bump SI back to point to delimeter 736 737 parse_ret: 0 00004A15 5F pop di 0 00004A16 C3 ret 740 741 742 ;----------- 743 nz_store_al: 744 ;----------- 745 ; Entry: 746 ; DI -> destination to conditionally initialize 747 ; CX == length of destination 748 ; AL == byte to initialize with 749 ; ZF set: do not initialize destination 750 ; Exit: 751 ; DI -> past destination (initial DI+CX) 752 ; Changed: 753 ; CX,DI 754 ; 0 00004A17 7502 jnz skip_store ; should we initialize? 0 00004A19 F3AA rep stosb ; Y: store them bytes 757 skip_store: 0 00004A1B 01CF add di,cx ; bump DI to post-dest position 0 00004A1D C3 ret 760 761 762 ;========== 763 parse_item: ; Parses item into fcb if item is specified 764 ;========== 765 ; 766 ; Entry: 767 ; SI -> item to parse (name or type) 768 ; DI -> fcb area to parse it into 769 ; CX == length of item 770 ; DH == parse_return 771 ; Exit: 772 ; SI -> past ending delimeter 773 ; DI -> past fcb area (initial DI + CX) 774 ; CH == If zero on enter zero on exit else 0-255 775 ; DH == updated parse_return w/possible wild bit set 776 ; DL == character delimiter @(SI-1) 777 ; Changed: 778 ; AX,CX,DX,SI,DI 779 ; 780 0 00004A1E B400 mov ah,FALSE ; specified item flag 782 parse_item_loop: 0 00004A20 AC lodsb ; get char 0 00004A21 E83400 call check_delimiters ; is it a delimiter? 0 00004A24 7625 jbe pi_pad_ret ; Y: the parse is complete 0 00004A26 E3F8 jcxz parse_item_loop ; if the name is full, skip the char 0 00004A28 88C4 mov ah,al ; flag name as present 0 00004A2A 3C3F cmp al,'?' ; is it a single wild char? 0 00004A2C 7408 je pi_set_wild ; Y: set wild flag 0 00004A2E 3C2A cmp al,'*' ; is it a multi-char wild card? 0 00004A30 7509 jne pi_store ; N: store it 0 00004A32 B03F mov al,'?' ; Y: fill with '?' to end of name 0 00004A34 F3AA rep stosb 794 pi_set_wild: 0 00004A36 80CE01 or dh,1 ; set wild flag 0 00004A39 E3E5 jcxz parse_item_loop ; skip store if name is now filled 797 pi_store: 0 00004A3B 49 dec cx ; another char done 0 00004A3C E8[0000] call dbcs_lead ; is it the 1st byte of kanji ? 0 00004A3F 7507 jne pi_store10 0 00004A41 46 inc si ; skip 2nd byte 0 00004A42 E3DC jcxz parse_item_loop ; can I copy both ? 0 00004A44 49 dec cx ; yes, do so 0 00004A45 AA stosb 0 00004A46 4E dec si ; point at second byte 0 00004A47 AC lodsb ; so we can copy it too.. 807 pi_store10: 0 00004A48 AA stosb ; put the char in the fcb 0 00004A49 EBD5 jmp parse_item_loop 810 pi_pad_ret: 0 00004A4B 88C2 mov dl,al ; DL = ending delimeter 0 00004A4D 08E4 or ah,ah ; the the item specified? 0 00004A4F 7404 jz pi_ret ; N: skip padding 0 00004A51 B020 mov al,' ' ; Y: pad to end with spaces 0 00004A53 F3AA rep stosb 816 pi_ret: 0 00004A55 01CF add di,cx ; bump DI out to end 0 00004A57 C3 ret 819 820 821 ;---------------- 822 check_delimiters: 823 ;---------------- 824 ; 825 ; Entry: 826 ; AL == char to check in list of delimiters 827 ; Exit: 828 ; AL == char changed to uppercase 829 ; CF set if it is one of the terminators: |"/\[]<> & ctrl chars != TAB 830 ; ZF set if it is one of the separators: .,+:;= SPACE & TAB 831 ; OR one of the non-ctrl terminators 832 ; 833 0 00004A58 3C61 cmp al,'a' ; check for lower case 0 00004A5A 7207 jb not_lower 0 00004A5C 3C7A cmp al,'z' 0 00004A5E 7703 ja not_lower 0 00004A60 245F and al,01011111b ; uppercase it, CF clear, ZF clear 0 00004A62 C3 ret 840 not_lower: 0 00004A63 51 push cx 0 00004A64 57 push di 0 00004A65 06 push es 0 00004A66 0E push cs 0 00004A67 07 pop es ; ES = Code segment 0 00004A68 BF[3E00] mov di,offset parse_separators 0 00004A6B B90700 mov cx,lengthof_parse_separators 0 00004A6E F2AE repne scasb ; is AL a separator? 0 00004A70 7409 je cpd_pop_ret ; Y: return ZF set 0 00004A72 B108 mov cl,lengthof_parse_terminators 0 00004A74 F2AE repne scasb ; is AL a terminator? 0 00004A76 F9 stc ; (set CF if true) 0 00004A77 7402 je cpd_pop_ret ; Y: return CF & ZF set 0 00004A79 3C20 cmp al,' ' ; (AL == ' ') ZF set, (AL < ' ') CF set 855 cpd_pop_ret: 0 00004A7B 07 pop es 0 00004A7C 5F pop di 0 00004A7D 59 pop cx 0 00004A7E C3 ret 860 861 ; 862 ; ***************************** 863 ; *** DOS Function 2A *** 864 ; *** Get Current Date *** 865 ; ***************************** 866 Public func2A 867 func2A: 868 ; 869 ; entry: None 870 ; 871 ; exit: cx = year (1980-2099) 872 ; dh = month (1-12) 873 ; dl = day (1-31) 874 ; al = DOS returns day of week here 875 ; 0 00004A7F E85F00 call ReadTimeAndDate ; Get the current Time and Date 0 00004A82 B9BC07 mov cx,1980 0 00004A85 030E[0000] add cx,[yearsSince1980] 879 ; mov dl,dayOfMonth 880 ; mov ah,month 0 00004A89 8B16[0000] mov dx,word ptr [dayOfMonth] 0 00004A8D A0[0000] mov al,[dayOfWeek] 0 00004A90 EB0D jmp f2C_10 ; exit via common routine 884 885 ; ***************************** 886 ; *** DOS Function 2C *** 887 ; *** Get Current Time *** 888 ; ***************************** 889 Public func2C 890 func2C: 891 ; 892 ; entry: None 893 ; 894 ; exit: ch = hours (0-23) 895 ; cl = minutes (0-59) 896 ; dh = seconds (0-59) 897 ; dl = Hunredths seconds (0-99) 898 ; al = 0 899 ; 0 00004A92 E84C00 call ReadTimeAndDate ; Get the current Time and Date 0 00004A95 8B0E[0200] mov cx,[biosDate+2] ; Get the Hour and Minute 0 00004A99 8B16[0400] mov dx,[biosDate+4] ; Get the Seconds and Hundredths 0 00004A9D 31C0 xor ax,ax ; return AL = 0 904 f2C_10: 0 00004A9F E8[0000] call return_CX ; and return to caller 0 00004AA2 E9[0000] jmp return_DX 907 908 909 910 ; ***************************** 911 ; *** DOS Function 2B *** 912 ; *** Set Current Date *** 913 ; ***************************** 914 Public func2B 915 func2B: 916 ; 917 ; entry: cx = year (1980-2099) 918 ; dh = month (1-12) 919 ; dl = day (1-31) 920 ; 921 ; exit: al = 00H success 922 ; = FFH failure 923 ; 0 00004AA5 E8BC00 call ConvertDate ; Convert to BIOS date 0 00004AA8 7211 jc f2B_20 ; Abort on Error 0 00004AAA 51 push cx ; save the converted date 0 00004AAB E83300 call ReadTimeAndDate ; Get the current Time and Date 0 00004AAE 8F06[0000] pop word [biosDate] ; new date, existing time 929 f2B_10: ; Set the current Time and Date 0 00004AB2 E80501 call rw_clock_common ; make sure clock is there/setup regs 0 00004AB5 E8[0000] call device_write ; Update the Date and Time 0 00004AB8 31C0 xor ax,ax 0 00004ABA C3 ret 934 935 f2B_20: 0 00004ABB B0FF mov al,0FFh ; return FAILURE 0 00004ABD C3 ret 938 939 ; ***************************** 940 ; *** DOS Function 2D *** 941 ; *** Set Current Time *** 942 ; ***************************** 943 Public func2D 944 func2D: 945 ; 946 ; entry: ch = hours (0-23) 947 ; cl = minutes (0-59) 948 ; dh = seconds (0-59) 949 ; dl = hundredth seconds (0-99) 950 ; 951 ; exit: al = 00H success 952 ; = FFH failure 953 ; 0 00004ABE 80FD17 cmp ch,23 ; Range check hours 0 00004AC1 77F8 ja f2B_20 0 00004AC3 80F93B cmp cl,59 ; Range check minutes 0 00004AC6 77F3 ja f2B_20 0 00004AC8 80FE3B cmp dh,59 ; Range check seconds 0 00004ACB 77EE ja f2B_20 0 00004ACD 80FA63 cmp dl,99 ; Range check hundredths 0 00004AD0 77E9 ja f2B_20 0 00004AD2 51 push cx ; save hours/mins 0 00004AD3 52 push dx ; save secs/hundredths 0 00004AD4 E80A00 call ReadTimeAndDate ; Get the current Time and Date 0 00004AD7 8F06[0400] pop word [biosDate+4] ; leave the date alone 0 00004ADB 8F06[0200] pop word [biosDate+2] ; but update the time 0 00004ADF EBD1 jmp f2B_10 ; Update the Date and Time 968 969 970 Public ReadTimeAndDate 971 972 ReadTimeAndDate: ; Get the current Time and Date 0 00004AE1 E8D600 call rw_clock_common ; make sure clock is there/setup regs 0 00004AE4 E8[0000] call device_read ; read the Date and Time 0 00004AE7 A1[0000] mov ax,[biosDate] ; get the BIOS date and convert 0 00004AEA 3B06[0000] cmp ax,[daysSince1980] ; (but only if necessary) 0 00004AEE 7501 jne NewDate 0 00004AF0 C3 ret 979 980 NewDate: 0 00004AF1 A3[0000] mov [daysSince1980],ax ; so we won't have to convert next time 0 00004AF4 40 inc ax ; Day number starting 1 Jan 1980 0 00004AF5 89C1 mov cx,ax ; save day count 0 00004AF7 40 inc ax ; convert to a sunday as 1/1/80 is tues 0 00004AF8 31D2 xor dx,dx 0 00004AFA BB0700 mov bx,7 0 00004AFD F7F3 div bx 0 00004AFF 8816[0000] mov [dayOfWeek],dl ; save day of week 989 0 00004B03 31D2 xor dx,dx 0 00004B05 89C8 mov ax,cx ; recover day count 992 0 00004B07 31FF xor di,di ; assume zero leap days 0 00004B09 83E83C sub ax,60 ; less than 60 days 0 00004B0C 720A jc no_leap_days ; means no leap days to subtract 0 00004B0E BBB505 mov bx,1461 ; 1461 = days in four years 0 00004B11 F7F3 div bx ; get number of leap years since 1980 0 00004B13 40 inc ax ; include 1980 0 00004B14 29C1 sub cx,ax ; normalize years to 365 days 0 00004B16 89C7 mov di,ax ; save proper leap day count 1001 no_leap_days: 1002 0 00004B18 31D2 xor dx,dx 0 00004B1A 91 xchg ax,cx ; DX:AX = years since 1980 * 365 0 00004B1B BB6D01 mov bx,365 0 00004B1E F7F3 div bx ; get number of years since 1980 0 00004B20 09D2 or dx,dx ; check for zero days left 0 00004B22 7504 jnz days_left 0 00004B24 48 dec ax ; dec year count 0 00004B25 BA6D01 mov dx,365 ; set day count to last day of last year 1011 days_left: 1012 0 00004B28 A3[0000] mov [yearsSince1980],ax ; save the year 0 00004B2B 96 xchg ax,si ; save in SI 1015 0 00004B2C 31DB xor bx,bx 0 00004B2E B90C00 mov cx,12 1018 get_month: ; find the appropriate month 0 00004B31 2E3B97[1800] cmp dx,[cs:totaldays + bx] 0 00004B36 7604 jbe got_month 0 00004B38 43 inc bx 0 00004B39 43 inc bx 0 00004B3A E2F5 loop get_month 1024 got_month: 0 00004B3C D1EB shr bx,1 ; BX = month 0 00004B3E 881E[0000] mov [month],bl 1027 0 00004B42 4B dec bx 0 00004B43 D1E3 shl bx,1 ; BX = index to previous months 0 00004B45 2E2B97[1800] sub dx,[cs:totaldays + bx] ; get days into this month 1031 0 00004B4A 83FB02 cmp bx,2 ; if it's FEB 29th we've lost a day 0 00004B4D 7510 jne not_leap_yr ; check it's FEB 0 00004B4F F7C60300 test si,3 0 00004B53 750A jnz not_leap_yr ; but is it a leap year ? 0 00004B55 D1EE shr si,1 0 00004B57 D1EE shr si,1 ; divide years by 4 0 00004B59 46 inc si ; include this year 0 00004B5A 39FE cmp si,di ; compare against leap day adjustment 0 00004B5C 7501 jne not_leap_yr 0 00004B5E 42 inc dx ; put 29th feb back again 1042 not_leap_yr: 0 00004B5F 8816[0000] mov [dayOfMonth],dl ; save the day of the month 0 00004B63 C3 ret 1045 1046 1047 ConvertDate: 0 00004B64 81E9BC07 sub cx,1980 ; Base year is 1980 0 00004B68 724E jc xset_date_error 0 00004B6A 83F978 cmp cx,2100-1980 ; Year in valid range ? 0 00004B6D 7349 jnc xset_date_error 0 00004B6F 88F3 mov bl,dh ; Month to BL 0 00004B71 30FF xor bh,bh 0 00004B73 4B dec bx ; Adjust month to 0-11 0 00004B74 80FB0C cmp bl,12 ; Month in valid range ? 0 00004B77 733F jnc xset_date_error 0 00004B79 88D0 mov al,dl ; Day of month 0 00004B7B 98 cbw 0 00004B7C F6C103 test cl,3 ; Leap year ? 0 00004B7F 750B jnz not_leap_year ; Jump if not 0 00004B81 80FE03 cmp dh,3 ; After February ? 0 00004B84 F5 cmc 0 00004B85 10E0 adc al,ah ; Increment days in current year if so 0 00004B87 80FA1D cmp dl,29 ; Day of month 29 ? 0 00004B8A 7408 jz day_valid ; Valid if so 1066 1067 not_leap_year: 0 00004B8C 4A dec dx 0 00004B8D 2E3A97[3200] cmp dl,[cs:monthdays + bx] ; Day of month within range for non-leap 1070 ; year ? 0 00004B92 7324 jnc xset_date_error 1072 1073 day_valid: 0 00004B94 D1E3 shl bx,1 0 00004B96 2E0387[1800] add ax,[cs:totaldays + bx] ; Get total days in current year 1076 0 00004B9B 50 push ax 1078 0 00004B9C B86D01 mov ax,365 0 00004B9F F7E1 mul cx ; Convert year to days since 1-1-1980 0 00004BA1 89C1 mov cx,ax 1082 1083 ; if total (ax) >= 60 (Feb 29 1980) then 1084 ; leap$days = (total - 60) / (365 * 4) + 1 1085 0 00004BA3 83E83C sub ax,60 ; Before first leap year date 0 00004BA6 720A jc noleap ; Jump if so 0 00004BA8 BBB405 mov bx,365*4 ; 4 years worth of days (365 * 4) 0 00004BAB 29D2 sub dx,dx 0 00004BAD F7F3 div bx ; Get number of leap years - 1 0 00004BAF 40 inc ax 0 00004BB0 01C1 add cx,ax ; CX now has total days including leap 1093 ; days 1094 1095 noleap: 0 00004BB2 49 dec cx 1097 0 00004BB3 58 pop ax 1099 0 00004BB4 01C1 add cx,ax ; Get total days since 1-1-1980 0 00004BB6 F8 clc 0 00004BB7 C3 ret 1103 1104 xset_date_error: 0 00004BB8 F9 stc 0 00004BB9 C3 ret 1107 1108 rw_clock_common: 0 00004BBA B90600 mov cx,6 ; read/write 6 characters 0 00004BBD BA[0000] mov dx,offset biosDate ; DX -> 6 byte buffer 0 00004BC0 C436[0000] les si,[clk_device] ; Get the address of the Clock Device 0 00004BC4 83FEFF cmp si,-1 ; Has a valid device been selected 0 00004BC7 7503 jne rw_clock_common10 0 00004BC9 83C402 add sp,2 ; discard near return address 1115 rw_clock_common10: 0 00004BCC C3 ret 1117 1118 1119 ; ***************************** 1120 ; *** DOS Function 38 *** 1121 ; *** Get/Set Country Data *** 1122 ; ***************************** 1123 Public func38 1124 func38: 0 00004BCD 30E4 xor ah,ah ; Generate 16 Bit country 0 00004BCF 3CFF cmp al,0FFh ; FF means country code in BX 0 00004BD1 7501 jne f38_10 0 00004BD3 93 xchg ax,bx ; AX = real country code 1129 f38_10: 0 00004BD4 92 xchg ax,dx ; DX = country 0 00004BD5 85D2 test dx,dx ; dos_AL = 0 get the current country 0 00004BD7 7404 jz f38_get 0 00004BD9 40 inc ax ; now check for dos_DX = FFFF 0 00004BDA 743C jz f38_set ; which means set country code 0 00004BDC 48 dec ax ; no, return buffer to normal 1136 f38_get: 0 00004BDD 85D2 test dx,dx ; Get current? 0 00004BDF 7504 jnz f38_g10 ; Yes 0 00004BE1 8B16[0000] mov dx,[cur_country] ; use current country 1140 f38_g10: 1141 ; look for (and if neccessary load) type 1 info into buffer 0 00004BE5 97 xchg ax,di ; ES:DI -> buffer 0 00004BE6 8B1E[0000] mov bx,[cur_cp] ; bx=codepage 0 00004BEA E81F00 call f38_get_info ; get info in current codepage 0 00004BED 7309 jnc f38_g20 0 00004BEF 16 push ss 0 00004BF0 1F pop ds 0 00004BF1 31DB xor bx,bx ; now try any codepage 0 00004BF3 E81600 call f38_get_info ; if none for current codepage 0 00004BF6 7239 jc f38_error ; No Match Found 1151 f38_g20: 0 00004BF8 8D7404 lea si,[EXCI_CI_DATAOFF + si] ; point at CI_, not EXCI_ data 0 00004BFB 8B5CFC mov bx,[si+CI_CODE] ; Return the selected country code 0 00004BFE B90C00 mov cx,CI_STATICLEN/2 0 00004C01 F3A5 rep movsw 1156 1157 %if NLSFUNC 0 00004C03 16 push ss 0 00004C04 1F pop ds 1160 ; call get_dseg ; DS back to PCMODE 1161 %endif 0 00004C05 E8[0000] call return_BX ; return country code in BX 0 00004C08 93 xchg ax,bx 0 00004C09 E9[0000] jmp return_AX_CLC ; and in AX 1165 1166 f38_get_info: 0 00004C0C 06 push es 0 00004C0D 57 push di 0 00004C0E 52 push dx ; save pointer to buffer 0 00004C0F B001 mov al,1 ; Get data list seperators etc... 0 00004C11 E8C501 call f65_get_info ; DS:SI -> extended country info buffer 0 00004C14 5A pop dx 0 00004C15 5F pop di 0 00004C16 07 pop es ; ES:DI -> users buffer 0 00004C17 C3 ret 1176 1177 f38_set: 0 00004C18 8B1E[0000] mov bx,[cur_cp] ; bx=codepage 0 00004C1C 231E[0000] and bx,[f38_flag] ; force CP to zero if 1st time here 0 00004C20 E81600 call f38_set_country ; Update the Internal Data Structures 0 00004C23 720C jc f38_error 1182 f38_s20: 0 00004C25 C706[0000]FFFF mov word [f38_flag],0FFFFh ; Country Code Set Successfully 0 00004C2B A1[0000] mov ax,[cur_country] ; and return the current country 0 00004C2E E9[0000] jmp return_AX_CLC ; to the user 1186 1187 1188 f38_error: 1189 1190 %if NLSFUNC 0 00004C31 16 push ss 0 00004C32 1F pop ds 1193 ; call get_dseg ; DS back to PCMODE 1194 %endif 0 00004C33 B8FEFF mov ax,ED_FILE ; This is the Error to return 0 00004C36 E9[0000] jmp error_exit 1197 1198 1199 f38_set_country: 1200 ; On Entry: 1201 ; BX = codepage 1202 ; DX = country 1203 ; On Exit: 1204 ; AX = error code 1205 ; preserve codepage/country info if there is an error (ie do type 1 last!) 1206 ; 0 00004C39 B002 mov al,2 ; Get uppercase & filename table 0 00004C3B BF[0000] mov di,offset Ucasetbl 0 00004C3E B9[0000] mov cx,info2_len 0 00004C41 E84600 call f38_update 0 00004C44 7240 jc f38_seterr 0 00004C46 B004 mov al,4 ; Get uppercase & filename table 0 00004C48 BF[0000] mov di,offset FileUcasetbl 0 00004C4B B9[0000] mov cx,info4_len 0 00004C4E E83900 call f38_update 0 00004C51 7233 jc f38_seterr 0 00004C53 B005 mov al,5 ; Get Legal file characters 0 00004C55 BF[0000] mov di,offset FileCharstbl 0 00004C58 B9[0000] mov cx,info5_len 0 00004C5B E82C00 call f38_update 0 00004C5E 7226 jc f38_seterr 0 00004C60 B006 mov al,6 ; Get Collating table 0 00004C62 BF[0000] mov di,offset Collatingtbl 0 00004C65 B9[0000] mov cx,info6_len 0 00004C68 E81F00 call f38_update 0 00004C6B 7219 jc f38_seterr 0 00004C6D B007 mov al,7 ; Get double byte character set table 0 00004C6F BF[0000] mov di,offset DBCS_tbl 0 00004C72 B9[0000] mov cx,info7_len 0 00004C75 E81200 call f38_update 0 00004C78 720C jc f38_seterr 0 00004C7A B001 mov al,1 ; Get data list seperators etc... 0 00004C7C BF[0000] mov di,offset country_data ; do last since this updates 0 00004C7F B9[0000] mov cx,info1_len ; cur_country/cur_cp 0 00004C82 E80500 call f38_update 1236 ; jc f38_seterr 1237 ; clc 0 00004C85 C3 ret 1239 f38_seterr: 0 00004C86 B8FEFF mov ax,ED_FILE ; return file not found error 0 00004C89 C3 ret 1242 1243 f38_update: 0 00004C8A 1E push ds ; save important registers 0 00004C8B 53 push bx ; codepage 0 00004C8C 51 push cx ; count for move 0 00004C8D 52 push dx ; country 0 00004C8E 57 push di ; destination offset for move 0 00004C8F 1E push ds ; destination segment 0 00004C90 E84601 call f65_get_info ; DS:SI -> buffer with country info 0 00004C93 07 pop es ; destination seg in ES 0 00004C94 5F pop di ; ES:DI -> destination of move 0 00004C95 5A pop dx ; country 0 00004C96 59 pop cx ; bytes to move 0 00004C97 5B pop bx ; codepage back again 0 00004C98 7202 jc f38_update10 ; any problems ? 0 00004C9A F3A4 rep movsb ; no, copy the data 1258 f38_update10: 0 00004C9C 1F pop ds ; DS back to PCMDSEG 0 00004C9D C3 ret 1261 1262 ; ***************************** 1263 ; *** DOS Function 65 *** 1264 ; *** Extended Country Data *** 1265 ; ***************************** 1266 ; 1267 ;CODEPAGE equ 437 ; Return Standard Code Page 1268 ; 1269 ; Get Extended Country Code Sub-Functions 1270 ; 0 00004C9E FFFF func65_dt dw 0FFFFh ; 00 Illegal Sub-Function 0 00004CA0 [0000] dw offset country_data ; 01 Extended Country Info 0 00004CA2 [0000] dw offset Ucasetbl ; 02 UpperCase Table 0 00004CA4 FFFF dw 0FFFFh ; 03 Invalid Subfunction 0 00004CA6 [0000] dw offset FileUcasetbl ; 04 FileName Upper Case Table 0 00004CA8 [0000] dw offset FileCharstbl ; 05 Valid Filename Characters 0 00004CAA [0000] dw offset Collatingtbl ; 06 Collating Sequence 0 00004CAC [0000] dw offset DBCS_tbl ; 07 DBCS Environment Vector 1279 func65_dtl equ (offset $ - offset func65_dt)/2 1280 1281 Public func65 1282 func65: 0 00004CAE 3C08 cmp al,func65_dtl ; is sub-function 0-7 ? 0 00004CB0 7265 jb func65_read_table 0 00004CB2 2C20 sub al,20h ; now check for 20-22 0 00004CB4 725E jb f65_invalid 0 00004CB6 7453 je func6520 ; it's upper case character 0 00004CB8 2C02 sub al,2 0 00004CBA 742B je func6522 0 00004CBC 7232 jb func6521 0 00004CBE 2C01 sub al,1 ; how about 6523 ? 0 00004CC0 7552 jnz f65_invalid 1293 ; jmp func6523 1294 1295 func6523: 1296 ;-------- 1297 ; On Entry: 1298 ; DX = character to check 1299 ; On Exit: 1300 ; AX = 0, No 1301 ; AX = 1, Yes 1302 ; AX = 2, neither 1303 ; 0 00004CC2 1E push ds 0 00004CC3 07 pop es 0 00004CC4 BF[0000] mov di,offset NoYesChars ; 'NnYy' 0 00004CC7 98 cbw ; assume No (AX=0) 0 00004CC8 92 xchg ax,dx ; AX = char, DX = answer 0 00004CC9 E8[0000] call dbcs_lead ; is it 1st of a DBCS pair 0 00004CCC 7507 jne func6523_10 0 00004CCE AF scasw ; check 'N' 0 00004CCF 7412 je func6523_30 0 00004CD1 42 inc dx ; assume Yes (DX=1) 0 00004CD2 AF scasw ; check 'Y' 0 00004CD3 EB0B jmp func6523_20 1316 func6523_10: 0 00004CD5 AE scasb ; check 'N' 0 00004CD6 740B je func6523_30 0 00004CD8 AE scasb ; check 'n' 0 00004CD9 7408 je func6523_30 0 00004CDB 42 inc dx ; assume Yes (DX=1) 0 00004CDC AE scasb ; check 'Y' 0 00004CDD 7404 je func6523_30 0 00004CDF AE scasb ; check 'y' 1325 func6523_20: 0 00004CE0 7401 je func6523_30 0 00004CE2 42 inc dx ; it's neither (DX=2) 1328 func6523_30: 0 00004CE3 92 xchg ax,dx ; return result in AX 0 00004CE4 E9[0000] jmp return_AX_CLC ; Return the Code Page 1331 1332 func6522: 1333 ;-------- 1334 ; Upper case ASCIIZ string at ES:DX 0 00004CE7 B9FFFF mov cx,0FFFFh ; calculate the length 0 00004CEA 89D7 mov di,dx ; of the string 1337 ; mov al,0 0 00004CEC F2AE repne scasb 0 00004CEE F7D1 not cx ; CX = length, including 0 1340 ; jmp func6521 ; now use upper case CX bytes 1341 1342 func6521: 1343 ;-------- 1344 ; Upper case string of CX bytes at ES:DX 0 00004CF0 E318 jcxz f6521_30 ; nothing to do? 0 00004CF2 89D6 mov si,dx 0 00004CF4 89D7 mov di,dx ; point SI & DI at string 1348 f6521_10: 0 00004CF6 26AC es lodsb ; read a character 0 00004CF8 E8[0000] call dbcs_lead ; is it 1st of a DBCS pair 0 00004CFB 7507 jne f6521_20 0 00004CFD AA stosb ; store 1st byte of this pair 0 00004CFE 26A4 es movsb 1354 ; copy 2nd byte 0 00004D00 49 dec cx ; 1st byte of pair 0 00004D01 E0F3 loopnz f6521_10 ; go around for another one 0 00004D03 C3 ret ; time to go... 1358 f6521_20: 0 00004D04 E8[0000] call toupper ; upper case the character 0 00004D07 AA stosb ; 0 00004D08 E2EC loop f6521_10 ; go and do another one 1362 f6521_30: 0 00004D0A C3 ret 1364 1365 func6520: 1366 ;-------- 1367 ; Upper case character DL 0 00004D0B 92 xchg ax,dx ; character in AX 0 00004D0C E8[0000] call toupper ; upper case it 0 00004D0F 88C2 mov dl,al ; return in AL and DL 0 00004D11 E9[0000] jmp return_DX ; set return code 1372 1373 f65_invalid: 1374 ;----------- 1375 ; short jump to invalid function 0 00004D14 E9[0000] jmp invalid_function 1377 1378 1379 func65_read_table: 1380 ;----------------- 0 00004D17 83F905 cmp cx,5 ; Check for valid buffer size 0 00004D1A 72F8 jb f65_invalid 0 00004D1C 98 cbw ; Get the request sub-function 0 00004D1D 89C6 mov si,ax ; into SI 0 00004D1F D1E6 shl si,1 0 00004D21 2E8BB4[8305] mov si,[cs:func65_dt + si] 0 00004D26 46 inc si ; is SI = 0FFFFh 0 00004D27 74EB jz f65_invalid ; if so it's an invalid function 0 00004D29 4E dec si 1390 0 00004D2A 83FAFF cmp dx,0ffffh 0 00004D2D 7504 jne f65_21 ; FFFF means 0 00004D2F 8B16[0000] mov dx,[cur_country] ; use default country 1394 f65_21: 0 00004D33 83FBFF cmp bx,0ffffh 0 00004D36 7504 jne f65_22 ; FFFF means 0 00004D38 8B1E[0000] mov bx,[cur_cp] ; use default codepage 1398 f65_22: 0 00004D3C E89A00 call f65_get_info ; DS:SI -> extended info for this pair 0 00004D3F B8FEFF mov ax,ED_FILE ; On Error return File Not Found 0 00004D42 7305 jnc f65_23 ; for any error 0 00004D44 16 push ss 0 00004D45 1F pop ds 0 00004D46 E9[0000] jmp error_exit ; so Quit 1405 f65_23: 0 00004D49 36C41E[0000] les bx,[ss:int21regs_ptr] ; point to callers registers 0 00004D4E 268B07 mov ax,[es:reg_AX + bx] ; get the subfunction number 0 00004D51 268B4F04 mov cx,[es:reg_CX + bx] ; this much data is requested 0 00004D55 268B7F0A mov di,[es:reg_DI + bx] ; Get the Parameter Block Offset 0 00004D59 268E4710 mov es,[es:reg_ES + bx] ; and Segment 0 00004D5D AA stosb ; fill in Info ID 0 00004D5E 3C01 cmp al,1 ; 1 is special - the rest 0 00004D60 7528 jne f65_30 ; want a DWORD ptr 0 00004D62 83F929 cmp cx,EXCI_MAXLEN ; Check CX against the sub-function 1 0 00004D65 7603 jbe f65_25 ; maximum and force CX to this value 0 00004D67 B92900 mov cx,EXCI_MAXLEN ; if it is greater 1417 f65_25: 0 00004D6A E8[0000] call return_CX ; Return the number of bytes transfered 0 00004D6D 83E903 sub cx,EXI_DATA_LEN ; Adjust count for 3 byte header 0 00004D70 89C8 mov ax,cx 0 00004D72 AB stosw ; fill in EXCI_LENGTH 0 00004D73 51 push cx ; Save the count and copy as much 0 00004D74 83F91C cmp cx,EXCI_STATLEN ; valid data a possible. IE at most 0 00004D77 7603 jbe f65_27 ; EXCI_STATLEN bytes 0 00004D79 B91C00 mov cx,EXCI_STATLEN 1426 f65_27: 0 00004D7C F3A4 rep movsb ; just copy the data 0 00004D7E 59 pop cx ; Zero the rest of the data 0 00004D7F 83E91C sub cx,EXCI_STATLEN ; Skip if no space left in users 0 00004D82 7612 jbe f65_40 ; buffer otherwise STOSB 0 00004D84 30C0 xor al,al 0 00004D86 F3AA rep stosb 0 00004D88 EB0C jmp f65_40 1434 1435 ; 1436 ; All function 65 sub-functions apart from 01 (Extended Country Info.) 1437 ; pass use this code to update the users parameter block. 1438 ; 1439 f65_30: 0 00004D8A B90500 mov cx,5 0 00004D8D E8[0000] call return_CX 0 00004D90 89F0 mov ax,si 0 00004D92 AB stosw ; fill in the DWORD ptr to the data 0 00004D93 8CD8 mov ax,ds 0 00004D95 AB stosw 1446 f65_40: 0 00004D96 16 push ss 0 00004D97 1F pop ds 1449 ; call get_dseg ; back to PCMDSEG 0 00004D98 A1[0000] mov ax,[cur_cp] ; ##jc## Is the Requested or Current 0 00004D9B E9[0000] jmp return_AX_CLC ; Return the Code Page 1452 1453 ; ***************************** 1454 ; *** DOS Function 66 *** 1455 ; ***Get/Set Global CodePage*** 1456 ; ***************************** 1457 ; 1458 Public func66 1459 func66: 0 00004D9E 98 cbw 0 00004D9F 48 dec ax 0 00004DA0 7406 jz f66_10 ; AL = 1, Get the Current CodePage 0 00004DA2 48 dec ax 0 00004DA3 7415 jz f66_20 ; AL = 2, Set the Current CodePage 0 00004DA5 E9[0000] jmp invalid_function ; Illegal Sub-Function return an Error 1466 1467 f66_10: ; Get the Current Code Page Info 0 00004DA8 8B1E[0000] mov bx,[cur_cp] ; Current CodePage 0 00004DAC E8[0000] call return_BX 0 00004DAF BAB501 mov dx,SYS_CP ; System CodePage 0 00004DB2 E8[0000] call return_DX 0 00004DB5 31C0 xor ax,ax 0 00004DB7 E9[0000] jmp return_AX_CLC 1474 1475 f66_20: ; Set the Current CodePage 0 00004DBA 8B16[0000] mov dx,[cur_country] ; The Codepage has changed, so update 0 00004DBE E878FE call f38_set_country ; Country Info and tables 0 00004DC1 7306 jnc f66_30 ; Reset the Current CodePage if 0 00004DC3 B8FEFF mov ax,ED_FILE ; and return the error 0 00004DC6 E9[0000] jmp error_exit 1481 f66_30: 0 00004DC9 8B1E[0000] mov bx,[cur_cp] ; select the new codepage 0 00004DCD E84500 call f66_select_cp ; Prepare CodePage Devices 0 00004DD0 7306 jnc f66_40 ; No Errors Skip Error Handler 0 00004DD2 B8BFFF mov ax,-65 ; Update Error Status do not generate 0 00004DD5 E8[0000] call error_ret ; a critical error but return 1487 ; "access denied" to the application 1488 f66_40: 0 00004DD8 C3 ret 1490 1491 1492 f65_get_info: 1493 ; On Entry: 1494 ; AL = info type 1495 ; BX = codepage (zero means any) 1496 ; DX = country 1497 ; On Exit: 1498 ; CY set if error 1499 ; DS:SI -> buffer with info in it 1500 ; 1501 ; NB. Remember to to Xlat fixups ! 1502 ; 0 00004DD9 3B16[0000] cmp dx,[cur_country] ; is it default country ? 0 00004DDD 7516 jne f65_p30 ; have we already got correct country ? 0 00004DDF 85DB test bx,bx ; CP zero special case and we will 0 00004DE1 7406 jz f65_p20 ; accept anything for this country 0 00004DE3 3B1E[0000] cmp bx,[cur_cp] ; otherwise is the codepage 0 00004DE7 750C jne f65_p30 ; in the default system ? 1509 f65_p20: 0 00004DE9 98 cbw ; make info type a word 0 00004DEA 89C6 mov si,ax ; into index register 0 00004DEC D1E6 shl si,1 ; now a word offset 0 00004DEE 2E8BB4[8305] mov si,[cs:func65_dt + si] ; pick up offset of correct table 0 00004DF3 EB07 jmp f65_p90 1515 f65_p30: 0 00004DF5 50 push ax 0 00004DF6 E81100 call f65_locate_and_read ; get info into a buffer at DS:SI 0 00004DF9 58 pop ax 0 00004DFA 720D jc f65_p_exit 1520 f65_p90: 0 00004DFC 3C01 cmp al,1 ; was it country info ? 0 00004DFE 7508 jne f65_p95 ; no, skip the fixup 0 00004E00 C74416[0000] mov word [CI_CASEOFF+EXCI_CI_DATAOFF + si],offset xlat_xlat 0 00004E05 8C5418 mov [CI_CASESEG+EXCI_CI_DATAOFF + si],ss 1525 f65_p95: 0 00004E08 F8 clc 1527 f65_p_exit: 0 00004E09 C3 ret 1529 1530 1531 ; 1532 ; ********************************************************************** 1533 ; *** Function 65 support - routines for seeking a country/codepage *** 1534 ; *** and loading the required information into the temp data area *** 1535 ; ********************************************************************** 1536 ; 1537 ; ************************************************** 1538 ; *** Open country.sys and search for the *** 1539 ; *** table of offsets for the given country/ *** 1540 ; *** codepage, read it in and exit. *** 1541 ; ************************************************** 1542 1543 f65_locate_and_read: 1544 ; Locate and Read info AL for Country DX Codepage BX 1545 %if NLSFUNC 0 00004E0A BF[0000] mov di,offset country_filename 1547 ; point at pathname to country.sys 0 00004E0D 91 xchg ax,cx ; get info into CL 0 00004E0E B8FE14 mov ax,14feh ; then call magic backdoor 1550 nlsfunc_int2f: 0 00004E11 F9 stc ; assume an error 0 00004E12 CD2F int 2fh ; to do the hard work 0 00004E14 C3 ret 1554 %else 1555 push ax 1556 call f65x_find_info ; Will need to load up the info 1557 pop ax 1558 jc f65_lr_exit ; so do it if we can. 1559 1560 mov dx,offset f65xx_temp_area 1561 mov cx,256 ; read 256 bytes into local buffer 1562 push ax 1563 call f65x_load_info ; Load required info 1564 pop ax 1565 jc f65_lr_exit 1566 mov ah,MS_X_CLOSE ; All done so 1567 mov bx,[c_handle] ; Close the file first 1568 call dos_entry ; before leaving 1569 ; jc f65_lr_exit 1570 mov si,offset f65xx_temp_area ; Tell subroutines where info is 1571 f65_lr_exit: 1572 ret 1573 ; 1574 ; Entry: dx=country code, bx=codepage 1575 ; Exit : carry set, and country.sys closed if failure 1576 ; country.sys open ready for more reads if success 1577 ; 1578 f65x_find_info: 1579 push es ; Save es 1580 push ds 1581 pop es ; Make es=ds 1582 mov [f65xx_country],dx 1583 mov [f65xx_codepage],bx 1584 mov dx,offset country_filename 1585 mov ax,(MS_X_OPEN*256)+0 ; Attempt to open country.sys 1586 test dx,dx 1587 stc 1588 jz f65x_40 1589 call dos_entry ; Handle should come back in ax 1590 jc f65x_40 1591 f65x_10: 1592 mov [c_handle],ax ; Save handle 1593 mov dx,[f65xx_country] 1594 cmp [f65xx_code],dx ; do we already have the information? 1595 jne f65x_30 ; No - get it from country.sys 1596 f65x_20: 1597 cmp [f65xx_cp],bx ; Does codepage agree too? 1598 je f65x_35 ; Yes so exit with no more ado 1599 f65x_30: 1600 mov dx,007Eh 1601 xor cx,cx ; Seek within country.sys 1602 mov bx,[c_handle] 1603 mov ax,(MS_X_LSEEK*256)+0 ; seek from begining 1604 call dos_entry 1605 jc f65x_err 1606 mov ah,MS_X_READ ; Now read the signature bytes and 1607 mov bx,[c_handle] ; check them 1608 mov cx,2 1609 mov dx,offset f65xx_sig 1610 call dos_entry 1611 jc f65x_err 1612 cmp word [f65xx_sig],VALID_SIG 1613 jne f65x_err ; If signature bad exit 1614 f65x_32: 1615 mov ah,MS_X_READ ; Read from country.sys header until 1616 mov bx,[c_handle] ; Country/codepage found or NULL 1617 mov cx,f65xx_ptable_len 1618 mov dx,offset f65xx_code 1619 call dos_entry 1620 jc f65x_err 1621 cmp word [f65xx_code],0 ; Found NULL so reqd combination 1622 je f65x_err ; was not found 1623 mov dx,[f65xx_code] ; Get the country/codepage values 1624 mov bx,[f65xx_cp] ; read from Country.SYS 1625 cmp dx,[f65xx_country] ; Check against the requested 1626 jne f65x_32 ; Country. 1627 cmp word [f65xx_codepage],0 ; If a codepage match is not 1628 jz f65x_35 ; then return success 1629 cmp bx,[f65xx_codepage] ; Check against the requested 1630 jne f65x_32 ; Codepage 1631 f65x_35: 1632 mov [f65xx_country],dx ; Force the Search Country and 1633 mov [f65xx_codepage],bx ; CodePage to be Updated 1634 f65x_40: 1635 pop es ; combination found so exit 1636 ret 1637 1638 f65x_err: 1639 pop es 1640 mov ah,MS_X_CLOSE ; On error close country.sys 1641 mov bx,[c_handle] ; and set the carry flag before 1642 call dos_entry ; leaving 1643 stc 1644 ret 1645 ; 1646 ; ************************************************** 1647 ; *** Load the type of information requested *** 1648 ; *** For the country currently active in the *** 1649 ; *** offset table *** 1650 ; ************************************************** 1651 ; 1652 ; Entry: al=type of info, dx=offset of buffer to read info into cx=no of bytes 1653 ; Exit : carry set, and country.sys closed if failure 1654 ; 1655 f65x_load_info: 1656 push es 1657 push cx 1658 push dx 1659 push ds ; Make es=ds 1660 pop es 1661 dec al ; 1=Data , 2=uppercase, 4=fuppercase 1662 sub bh,bh ; 5=filechars, 6=Collating table 1663 mov bl,al ; 7=DBCS table 1664 shl bx,1 ; Retrieve relevant offset 1665 mov dx,[f65xx_data + bx] 1666 xor cx,cx ; Seek within country.sys 1667 mov bx,[c_handle] 1668 mov ax,(MS_X_LSEEK*256)+0 ; seek from begining 1669 call dos_entry 1670 pop dx ; Get buffer address back 1671 pop cx ; and number of bytes to read 1672 jc f65x_err 1673 test ax,ax ; zero offset is a problem 1674 jz f65x_err ; (probably DBCS with old COUNTRY.SYS) 1675 mov ah,MS_X_READ ; Now read that info into our data area 1676 mov bx,[c_handle] 1677 call dos_entry ; Return when read is done 1678 jc f65x_err 1679 pop es 1680 ret 1681 %endif 1682 1683 ; 1684 ; This function scans the complete device list and prepares 1685 ; all devices which support codepage. 1686 ; 1687 ; On Entry: 1688 ; BX = codepage 1689 ; On Exit: 1690 ; AX = error code 1691 1692 DA_CODEPAGE equ DA_CHARDEV+DA_IOCTL+DA_GETSET 1693 1694 f66_select_cp: 1695 %if NLSFUNC 0 00004E15 B8FF14 mov ax,14ffh ; then call magic backdoor 0 00004E18 EBF7 jmp nlsfunc_int2f ; to do the hard work 1698 %else 1699 push ds 1700 mov [f66_cp],bx ; Save requested CodePage 1701 mov word [preperr],0000 ; Initialize Prepare Error 1702 push ds 1703 pop es 1704 mov bx,offset dev_root ; Get the Root of the Device List 1705 f66_p10: ; Skip the NUL Device and check 1706 lds bx,[DH_NEXT + bx] ; each character device for CodePage 1707 cmp bx,0FFFFh 1708 jz f66_p50 ; Support. 1709 mov ax,[DH_ATTRIB + bx] 1710 and ax,DA_CODEPAGE ; Check for a Character Device which 1711 cmp ax,DA_CODEPAGE ; supports IOCTL strings and GETSET 1712 jne f66_p10 ; otherwise skip the device 1713 1714 push bx 1715 lea si,[DH_NAME + bx] ; Found a matching device so 1716 mov di,offset prepname ; open the device and select the 1717 mov cx,8 ; requested codepage 1718 1719 f66_p20: 1720 lodsb 1721 cmp al,' ' 1722 jz f66_p30 1723 stosb 1724 loop f66_p20 1725 1726 f66_p30: 1727 xor al,al 1728 stosb 1729 mov ax,(MS_X_OPEN*256)+1 ; Open the device name for 1730 mov dx,offset prepname ; Write Access 1731 call dos_entry 1732 jc f66_perr 1733 mov bx,ax ; Save Device Handle in BX 1734 1735 mov si,[es:f66_cp] ; Get Requested CodePage in SI 1736 mov dx,offset cp_packet ; Offset of CodePage Struct 1737 mov cx,006Ah ; Get Unknown CodePage 1738 mov ax,(MS_X_IOCTL*256)+0Ch ; Generic IOCTL function 1739 call dos_entry ; Make function Call 1740 jc f66_p32 ; Error so Select requested Code Page 1741 1742 cmp si,[es:cp_cpid] 1743 jz f66_p35 ; If this the currently selected 1744 f66_p32: ; skip the select CodePage 1745 mov [es:cp_cpid],si 1746 mov dx,offset cp_packet ; Offset of CodePage Struct 1747 mov cx,004Ah ; Select Unkown CodePage 1748 mov ax,(MS_X_IOCTL*256)+0Ch ; Generic IOCTL function 1749 call dos_entry ; Make function Call 1750 jnc f66_p35 ; No Error so skip the error 1751 f66_p33: 1752 mov [es:preperr],ax ; save 1753 1754 f66_p35: 1755 mov ah,MS_X_CLOSE ; Close the device and check 1756 call dos_entry ; for more devices to be prepared 1757 jmp f66_p40 1758 1759 f66_perr: 1760 mov [es:preperr],ax ; Save the error code and try the 1761 f66_p40: ; next device in the chain 1762 pop bx ; Restore the Device offset 1763 jmp f66_p10 ; and continue 1764 1765 f66_p50: ; All device have been prepared 1766 pop ds ; now return the last error code 1767 mov ax,[preperr] ; in AX 1768 or ax,ax 1769 ret 1770 %endif 1771 1772 PCM_CODE ends 1773 === Switch to base=00C180h -> "PCMODE_DSIZE" 1774 section PCMODE_DSIZE public align=16 class=DATA 1775 extrn swap_indos:word 1776 PCMODE_DSIZE ends 1777 === Switch to base=000000h -> "PCM_RODATA" 1778 section PCM_RODATA public align=2 class=CODE 1779 ; 1780 ; Get Internal Data DOS function 5Dh 1781 ; 0 0000B988 [5000] func5D_ft dw f5D00 0 0000B98A [6D00] dw f5D01 ; Commit All 0 0000B98C [8200] dw f5D02 ; Close File By Name 0 0000B98E [D400] dw f5D03 ; Close All Host Files 0 0000B990 [D400] dw f5D04 ; Close Process Host Files 0 0000B992 [D900] dw f5D05 ; Get Open File List 0 0000B994 [EA00] dw f5D06 ; Get DOS Data Area 0 0000B996 [4A00] dw f5D_msnet ; f5D07 ; Get Truncate Flag used 1790 ; with Redirected Dev I/O 0 0000B998 [4A00] dw f5D_msnet ; f5D08 ; Set Truncate Flag with 1792 ; with Redirected Dev I/O 0 0000B99A [4A00] dw f5D_msnet ; f5D09 ; Close All Spool Streams 0 0000B99C [0A01] dw f5D0A ; Set Extended Error Info 1795 func5D_ftl equ (offset $ - offset func5D_ft)/2 0 0000B99E [0000] dw invalid_function 1797 1798 ; 1799 ; Data used by the Binary format Time and Date routines 1800 ; 0 0000B9A0 00001F003B005A0078 totaldays dw 0,31,59,90,120,151,181,212,243,273,304,334,0ffffh 0 0000B9A9 009700B500D400F300 0 0000B9B2 110130014E01FFFF 0 0000B9BA 1F1C1F1E1F1E1F1F1E monthdays db 31,28,31,30,31,30,31,31,30,31,30,31 0 0000B9C3 1F1E1F 1803 0 0000B9C6 092E2C2B3A3B3D parse_separators db TAB,'.,+:;=' 1805 lengthof_parse_separators equ $ - parse_separators 0 0000B9CD 7C222F5C5B5D3C3E parse_terminators db '|"/\[]<>' 1807 lengthof_parse_terminators equ $ - parse_terminators 1808 1809 PCM_RODATA ends 1810 === Switch to base=00C180h -> "PCMODE_DATA" 1811 section PCMODE_DATA public align=2 class=DATA 1812 extrn internal_data:word 1813 extrn error_code:word 1814 extrn error_class:byte 1815 extrn error_action:byte 1816 extrn error_locus:byte 1817 extrn error_dev:word 1818 1819 extrn indos_flag:word 1820 extrn bootDrv:byte 1821 extrn current_psp:word 1822 extrn break_flag:byte 1823 extrn dma_offset:word 1824 extrn dma_segment:word 1825 extrn fcb_search_buf:byte 1826 extrn func52_data:byte ; Internal Data Table Area 1827 extrn int21regs_ptr:dword 1828 extrn lock_tables:dword 1829 extrn unlock_tables:dword 1830 extrn share_stub:dword 1831 extrn remote_call:word ; set to FF if remote machine operation 1832 extrn swap_always:word 1833 extrn switch_char:byte 1834 extrn owning_psp:word 1835 extrn machine_id:word 1836 extrn country_data:byte 1837 extrn cur_country:word 1838 extrn cur_cp:word 1839 extrn verify_flag:byte 1840 1841 extrn clk_device:dword ; Clock Device Driver Address 1842 extrn biosDate:word 1843 extrn daysSince1980:word 1844 extrn yearsSince1980:word 1845 extrn month:byte 1846 extrn dayOfWeek:byte 1847 extrn dayOfMonth:byte 1848 extrn hour:byte 1849 extrn minute:byte 1850 extrn second:byte 1851 extrn hundredth:byte 1852 extrn WindowsHandleCheck:byte 1853 1854 SYS_CP equ 437 ; System CodePage 1855 PCMODE_DATA ends 1856 === Switch to base=00C180h -> "GLOBAL_DATA" 1857 section GLOBAL_DATA public align=2 class=DATA 1857 ****************** warning: segment attributes specified on redeclaration of segment: ignoring [-w+other] 1858 0 000012BC 0000 f38_flag dw 0 ; Country Code Selected Successfully 1860 1861 %if NLSFUNC ne TRUE 1862 extrn dev_root:dword 1863 1864 f66_cp dw 0 ; INT21/66 Local Variable 1865 cp_packet dw 2 ; Packet Size 1866 cp_cpid dw 0 ; Request CodePage 1867 db 0,0 ; Packet Terminators 1868 1869 preperr dw 0 ; Prepare function Error Code 1870 prepname db 9 dup (0) ; Reserved for ASCIIZ Device Name 1871 1872 ; 1873 ; Area for country.sys current pointer table 1874 ; (these are all offsets into country.sys) 1875 ; 1876 f65xx_code dw 0 ; Country code 1877 f65xx_cp dw 0 ; Code page 1878 dw 0 ; +1 reserved 1879 f65xx_data dw 0 ; Data area 1880 dw 0 ; Upper case table 1881 dw 0 ; +1 reserved 1882 dw 0 ; Filename upper case table 1883 dw 0 ; Legal file characters 1884 dw 0 ; Collating table 1885 dw 0 ; Double byte character set lead byte table 1886 f65xx_ptable_len equ offset $ - offset f65xx_code 1887 1888 f65xx_temp_area db 256 dup (0) ; Data area for extended country info 1889 f65xx_codepage dw 0 1890 f65xx_country dw 0 1891 f65xx_sig dw 0 ; Signature 1892 c_handle dw 0 1893 1894 %endif ;not NLSFUNC 1895 1896 GLOBAL_DATA ends 1897 1898 end === Trace listing source: drdos/bin/support.lst 1 ; File : $SUPPORT.A86$ 2 ; 3 ; Description : 4 ; 5 ; Original Author : DIGITAL RESEARCH 6 ; 7 ; Last Edited By : $CALDERA$ 8 ; 9 ;-----------------------------------------------------------------------; 10 ; Copyright Work of Caldera, Inc. All Rights Reserved. 11 ; 12 ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, 13 ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. 14 ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES 15 ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF 16 ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO 17 ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE 18 ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE 19 ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, 20 ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, 21 ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, 22 ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF 23 ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT 24 ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND 25 ; CIVIL LIABILITY. 26 ;-----------------------------------------------------------------------; 27 ; 28 ; *** Current Edit History *** 29 ; *** End of Current Edit History *** 30 ; 31 ; $Log$ 32 ; SUPPORT.A86 1.11 93/11/29 13:39:28 33 ; Don't rely on DS when return_ called 34 ; ENDLOG 35 ; 36 ; The following Support routines are provided for both the 37 ; handle and FCB functions which require critical error handler 38 ; support. 39 ; 40 ; 15 Jun 88 Modify the SYSDAT and SUPERVISOR variables to enable 41 ; the relocation of the BDOS into high memory 42 ; 5 Jan 89 Only set PCKBD mode if we own the default console 43 ; 9 Mar 89 Support a split PCMODE and SYSDAT Segments 44 ; 22 Sep 89 LDT support routine added 45 ; 29 Jan 90 Int 2A critical section support added to dpbdos_entry 46 ; 7 Mar 90 Convert to register preserved function calls 47 ; 4 May 90 DRDOS int3x handlers removed (they are pointed to IRET 48 ; in PCMODE_DATA by INIT.PCM) 49 ; 12 Dec 90 keep error server number inverted so local = 0, more compatible 50 51 ; 52 53 group PCMDATA PCMODE_DATA FDOS_DSEG 54 group PCMCODE PCM_CODE 55 56 ASSUME DS:PCMDATA 57 58 [list -] 64 === Switch to base=000000h -> "PCM_CODE" 65 section PCM_CODE public align=1 class=CODE 66 extrn error_exit:near ; Standard Error Exit Routine 67 extrn fcberror_exit:near ; Special FCB function Error Exit 68 extrn fdos_entry:near 69 extrn get_dseg:near 70 71 ; 72 ; STRLEN determines the length of the string passed in DS:SI 73 ; and returns the byte length in CX. 74 ; 75 Public strlen 76 strlen: 0 00004E1A 06 push es 0 00004E1B 57 push di 0 00004E1C 1E push ds 0 00004E1D 07 pop es 0 00004E1E 89F7 mov di,si 0 00004E20 B9FFFF mov cx,0FFFFh 0 00004E23 28C0 sub al,al 0 00004E25 F2AE repnz scasb 0 00004E27 5F pop di 0 00004E28 07 pop es 0 00004E29 F7D1 not cx 0 00004E2B 49 dec cx 0 00004E2C C3 ret 90 91 ; 92 ; This routine sets the address to be returned to by the 93 ; FDOS when an error has occured and the RETRY request has been 94 ; made. The set_retry routine should be used as follows:- 95 ; 96 ; mov al,Valid Error Responses 97 ; call set_retry 98 ; Init All FDOS Parameters 99 ; call fdos_crit 100 ; 101 ; NB. For register model return with AX = dos_AL extended to 16 bit 102 103 Public set_retry_RF 104 set_retry_RF: 0 00004E2D B018 mov al,OK_RF ; Valid to RETRY or FAIL 106 ; jmp set_retry ; (the most common case) 107 108 Public set_retry 109 set_retry: 0 00004E2F A2[0000] mov [valid_flg],al ; Save Valid Error Reponses 0 00004E32 8F06[0000] pop word [retry_off] ; Save the Routine Address 0 00004E36 8926[0000] mov [retry_sp],sp ; and the Stack Pointer 0 00004E3A 88E0 mov al,ah ; get function number 0 00004E3C 30E4 xor ah,ah ; make it a word 0 00004E3E A3[0000] mov [FD_FUNC],ax ; save it for the FDOS 0 00004E41 1E push ds 0 00004E42 53 push bx 0 00004E43 C51E[0000] lds bx,[int21regs_ptr] ; point to users registers 0 00004E47 836716FE and word [reg_FLAGS + bx],~ CARRY_FLAG 0 00004E4B 8A07 mov al,[reg_AL + bx] ; clear CY assuming we will succeed 0 00004E4D 5B pop bx ; and reload AL with entry value 0 00004E4E 1F pop ds 0 00004E4F FF26[0000] jmp near [retry_off] 124 125 ; 126 ; The FDOS routine executes the CCP/M FDOS function using the 127 ; static FDOS parameter block defined in the Data Segment. 128 ; 129 Public fdos_crit 130 fdos_crit: 0 00004E53 E84300 call fdos_nocrit 0 00004E56 83F8A6 cmp ax,ED_LASTERROR ; Compare against last error code 0 00004E59 731D jnb fdos_error ; if NOT below then is ERROR CODE 0 00004E5B 09C0 or ax,ax ; Reset the Carry Flag and Return 0 00004E5D C3 ret 136 137 Public fdos_ax_crit 138 fdos_ax_crit: 0 00004E5E E83800 call fdos_nocrit 0 00004E61 83F8A6 cmp ax,ED_LASTERROR ; Compare against last error code 0 00004E64 7312 jnb fdos_error ; if NOT below then is ERROR CODE 0 00004E66 09C0 or ax,ax ; Reset the Carry Flag and Return 143 ; jmp return_AX_CLC ; Save the Return Code 144 145 Public return_AX_CLC 146 return_AX_CLC: 147 ;------------- 148 ; On Entry: 149 ; AX to be returned to caller in AX 150 ; On Exit: 151 ; ES:DI trashed 152 ; 0 00004E68 1E push ds 0 00004E69 57 push di 0 00004E6A 36C53E[0000] lds di,[ss:int21regs_ptr] 0 00004E6F 8905 mov [reg_AX + di],ax ; return AX to caller 0 00004E71 836516FE and word [reg_FLAGS + di],~ CARRY_FLAG 0 00004E75 5F pop di 0 00004E76 1F pop ds 0 00004E77 C3 ret 161 162 163 fdos_error: ; Process the Error 0 00004E78 3B26[0000] cmp sp,[retry_sp] ; Is the user expecting use to 0 00004E7C 7503 jnz fdos_e10 ; return or use the default handler 0 00004E7E E9[0000] jmp error_exit ; If CALLed then return with the error 167 fdos_e10: ; to the calling routine. 0 00004E81 F9 stc 0 00004E82 C3 ret 170 171 Public fcbfdos_crit 172 fcbfdos_crit: 0 00004E83 E81300 call fdos_nocrit 0 00004E86 83F8A6 cmp ax,ED_LASTERROR ; Compare against last error code 0 00004E89 7303 jnb fcbfdos_error ; if NOT below then is ERROR CODE 0 00004E8B 09C0 or ax,ax ; Reset the Carry Flag and Return 0 00004E8D C3 ret 178 179 fcbfdos_error: ; Process the Error 0 00004E8E 3B26[0000] cmp sp,[retry_sp] ; Is the user expecting use to 0 00004E92 7503 jnz fcbfdos_e10 ; return or use the default handler 0 00004E94 E9[0000] jmp fcberror_exit ; If CALLed then return with the error 183 fcbfdos_e10: ; to the calling routine. 0 00004E97 F9 stc 0 00004E98 C3 ret 186 187 Public fdos_nocrit 188 fdos_nocrit: 0 00004E99 BA[0000] mov dx,offset fdos_data ; point to fdos parameter block 0 00004E9C 1E push ds 0 00004E9D 06 push es 0 00004E9E 56 push si 0 00004E9F 57 push di 0 00004EA0 55 push bp 0 00004EA1 E8[0000] call fdos_entry ; BDOS module entry point 0 00004EA4 09C0 or ax,ax ; Set the Flags 0 00004EA6 5D pop bp 0 00004EA7 5F pop di 0 00004EA8 5E pop si 0 00004EA9 07 pop es 0 00004EAA 1F pop ds 0 00004EAB C3 ret 203 204 205 Public reload_ES 206 reload_ES: 207 ; On Entry: 208 ; None 209 ; On Exit: 210 ; ES = callers ES 211 ; All regs preserved 212 ; 0 00004EAC 53 push bx 0 00004EAD 36C41E[0000] les bx,[ss:int21regs_ptr] 0 00004EB2 268E4710 mov es,[es:reg_ES + bx] ; reload with callers ES 0 00004EB6 5B pop bx 0 00004EB7 C3 ret 218 219 220 Public return_BX 221 return_BX: 222 ;--------- 223 ; On Entry: 224 ; BX to be returned to caller in BX 225 ; On Exit: 226 ; All regs preserved 227 ; 0 00004EB8 1E push ds 0 00004EB9 56 push si 0 00004EBA 36C536[0000] lds si,[ss:int21regs_ptr] 0 00004EBF 895C02 mov [reg_BX + si],bx ; return BX to caller 0 00004EC2 5E pop si 0 00004EC3 1F pop ds 0 00004EC4 C3 ret 235 236 Public return_CX 237 return_CX: 238 ;--------- 239 ; On Entry: 240 ; CX to be returned to caller in CX 241 ; On Exit: 242 ; All regs preserved 243 ; 0 00004EC5 1E push ds 0 00004EC6 53 push bx 0 00004EC7 36C51E[0000] lds bx,[ss:int21regs_ptr] 0 00004ECC 894F04 mov [reg_CX + bx],cx ; return CX to caller 0 00004ECF 5B pop bx 0 00004ED0 1F pop ds 0 00004ED1 C3 ret 251 252 Public return_DX 253 return_DX: 254 ;--------- 255 ; On Entry: 256 ; DX to be returned to caller in DX 257 ; On Exit: 258 ; All regs preserved 259 ; 0 00004ED2 1E push ds 0 00004ED3 53 push bx 0 00004ED4 36C51E[0000] lds bx,[ss:int21regs_ptr] 0 00004ED9 895706 mov [reg_DX + bx],dx ; return DX to caller 0 00004EDC 5B pop bx 0 00004EDD 1F pop ds 0 00004EDE C3 ret 267 268 PCM_CODE ends 269 === Switch to base=00C180h -> "PCMODE_DATA" 270 section PCMODE_DATA public align=2 class=DATA 271 272 273 extrn current_psp:word 274 extrn DBCS_tbl:word ; double byte character set table 275 extrn int21regs_ptr:dword 276 extrn retry_off:word 277 extrn retry_sp:word 278 extrn valid_flg:byte 279 280 PCMODE_DATA ends 281 282 end 283 === Trace listing source: drdos/bin/dosmem.lst 1 ; File : $DOSMEM.ASM$ 2 ; 3 ; Description : 4 ; 5 ; Original Author : DIGITAL RESEARCH 6 ; 7 ; Last Edited By : $CALDERA$ 8 ; 9 ;-----------------------------------------------------------------------; 10 ; Copyright Work of Caldera, Inc. All Rights Reserved. 11 ; 12 ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, 13 ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. 14 ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES 15 ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF 16 ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO 17 ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE 18 ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE 19 ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, 20 ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, 21 ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, 22 ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF 23 ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT 24 ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND 25 ; CIVIL LIABILITY. 26 ;-----------------------------------------------------------------------; 27 ; 28 ; *** Current Edit History *** 29 ; *** End of Current Edit History *** 30 ; $Log$ 31 ; DOSMEM.A86 1.13 94/12/01 10:05:21 32 ; now freeing UMBs also during program termination 33 ; DOSMEM.A86 1.12 93/07/20 22:46:25 34 ; dmd_upper_root defaults to FFFF 35 ; DOSMEM.A86 1.10 93/06/18 21:00:11 36 ; Remove historic CDOS comment 37 ; ENDLOG 38 ; 39 40 group PCMDATA PCMODE_DATA FDOS_DSEG 41 group PCMCODE PCM_CODE 42 43 ASSUME DS:PCMDATA 44 45 [list -] 50 51 BEST_FIT equ 01h ; allocate BEST match memory block 52 LAST_FIT equ 02h ; allocate LAST matching memory block 53 UPPER_FIT equ 80h ; preferably allocate from upper memory 54 UPPER_ONLY_FIT equ 40h ; only allocate from upper memory 55 56 FIRST_FIT equ 04h ; we use this internally... 57 === Switch to base=000000h -> "PCM_CODE" 58 section PCM_CODE public align=1 class=CODE 59 extrn error_exit:near ; Standard Error Handler 60 extrn return_AX_CLC:near 61 extrn return_BX:near 62 extrn reload_ES:near 63 extrn toupper:near 64 65 ; ***************************** 66 ; *** DOS Function 48 *** 67 ; *** Allocate Memory Block *** 68 ; ***************************** 69 ; 70 Public func48 71 func48: ; bx = request size 0 00004EDF FF1E[0000] call far [lock_tables] ; lock global tables 0 00004EE3 E85401 call search_mem ; look for block bx or bigger 0 00004EE6 7252 jc memory_avbl_error ; skip on error 0 00004EE8 F606[0000]02 test byte [mem_strategy],LAST_FIT ; is it last fit ? 0 00004EED 740E jz f48_10 ; no, use from begining 0 00004EEF 89C8 mov ax,cx ; work out how much we have 0 00004EF1 29D8 sub ax,bx ; to leave free 0 00004EF3 7408 je f48_10 0 00004EF5 48 dec ax 0 00004EF6 89C3 mov bx,ax 0 00004EF8 E80F02 call make_dmd ; allocate this DMD as free 0 00004EFB 89CB mov bx,cx ; real block is the next one 84 f48_10: 0 00004EFD A1[0000] mov ax,[current_psp] ; Change the Owner 0 00004F00 26A30100 mov [es:DMD_PSP],ax ; we now own this block 87 0 00004F04 06 push es 0 00004F05 E80202 call make_dmd ; make new DMD for allocated mem 0 00004F08 58 pop ax 0 00004F09 40 inc ax ; return starting segment 0 00004F0A EB27 jmp memory_exit ; unlock global tables 93 94 95 ; ***************************** 96 ; *** DOS Function 49 *** 97 ; *** Free Memory Block *** 98 ; ***************************** 99 ; 100 Public func49 101 func49: 0 00004F0C FF1E[0000] call far [lock_tables] ; lock global tables 0 00004F10 E82302 call get_dmd ; es -> dmd 0 00004F13 722A jc memory_error ; skip if block invalid 0 00004F15 26A10100 mov ax,[es:DMD_PSP] ; get owner field 0 00004F19 3B06[0000] cmp ax,[dmd_owner] 0 00004F1D 8CC0 mov ax,es ; return DMD address in AX 0 00004F1F 7208 jb func49_10 0 00004F21 8B16[0000] mov dx,[dmd_address] ; nothing below this block get's freed 0 00004F25 39D0 cmp ax,dx ; should we free it ? 0 00004F27 7202 jb func49_20 ; no, give it a new owner 112 func49_10: 0 00004F29 31D2 xor dx,dx ; yes, owner = 0 means free block 114 func49_20: 0 00004F2B 2689160100 mov [es:DMD_PSP],dx ; free/set new owner 0 00004F30 E8A901 call merge_mem ; merge with adjacent free blocks 117 ; jmp memory_exit 118 119 ; centralised exit point to unlock system tables 120 121 memory_exit: 122 ;----------- 123 ; On Entry: 124 ; AX = return value 125 ; On Exit 126 ; None 127 ; 0 00004F33 FF1E[0000] call far [unlock_tables] ; unlock global tables 0 00004F37 E9[0000] jmp return_AX_CLC ; return DMD address 130 131 memory_avbl_error: 0 00004F3A 89CB mov bx,cx 0 00004F3C E8[0000] call return_BX ; return biggest block available 134 memory_error: 0 00004F3F FF1E[0000] call far [unlock_tables] ; unlock global tables 0 00004F43 C606[0000]05 mov byte [locus],LOC_MEMORY 0 00004F48 E9[0000] jmp error_exit ; Jump to error handler 138 139 140 ; ***************************** 141 ; *** DOS Function 4A *** 142 ; *** Alter Memory Block *** 143 ; ***************************** 144 ; 145 Public func4A 146 func4A: 0 00004F4B FF1E[0000] call far [lock_tables] ; lock global tables 0 00004F4F E8E401 call get_dmd ; es -> dmd 0 00004F52 72EB jc memory_error ; skip if block invalid 150 0 00004F54 26FF360300 push word [es:DMD_LEN] ; save the current DMD length 0 00004F59 E88001 call merge_mem ; pick up unallocated blocks 0 00004F5C 58 pop ax ; return original DMD length 0 00004F5D 72E0 jc memory_error ; if dmd's destroyed 155 0 00004F5F B8F8FF mov ax,ED_MEMORY ; assume insufficient mem 0 00004F62 268B0E0300 mov cx,[es:DMD_LEN] ; cx = available size 0 00004F67 39D9 cmp cx,bx ; if avail < req, then 0 00004F69 72CF jb memory_avbl_error ; return maximum possible 160 0 00004F6B A1[0000] mov ax,[current_psp] ; Force this block to be owned by the 0 00004F6E 26A30100 mov [es:DMD_PSP],ax ; current PSP. MACE Utilities 163 0 00004F72 E89501 call make_dmd ; new block on top 0 00004F75 E8[0000] call reload_ES 0 00004F78 8CC0 mov ax,es 0 00004F7A EBB7 jmp memory_exit 168 169 ; ***************************** 170 ; *** DOS Function 58 *** 171 ; *** Get/Set Alloc Strategy*** 172 ; ***************************** 173 ; 174 ; On Entry:- AL == 0 Get Allocation Strategy 175 ; AL == 1 Set Allocation Strategy 176 ; AL == 2 Get Upper Memory Link 177 ; AL == 3 Set Upper Memory Link 178 Public func58 179 180 func58: 0 00004F7C FF1E[0000] call far [lock_tables] ; lock global tables 0 00004F80 3C03 cmp al,3 0 00004F82 770E ja f58_error ; Range Check Sub-Function 0 00004F84 98 cbw ; AH = 0 0 00004F85 89C6 mov si,ax 0 00004F87 01F6 add si,si ; SI = word offset of sub-function 0 00004F89 2EFF94[B800] call [cs:f58_tbl + si] ; execute the sub-function 0 00004F8E 73A3 jnc memory_exit ; return the result 0 00004F90 EBAD jmp memory_error ; or the error 190 191 192 f58_error: 0 00004F92 B8FFFF mov ax,ED_FUNCTION 0 00004F95 EBA8 jmp memory_error 195 0 00004F97 [C000] f58_tbl dw f58_get_strategy 0 00004F99 [C400] dw f58_set_strategy 0 00004F9B [CB00] dw f58_get_link 0 00004F9D [D100] dw f58_set_link 200 201 f58_get_strategy: 202 ; mov ah,0 ; AX = subfunction = 0-3 0 00004F9F A0[0000] mov al,[mem_strategy] 204 ; clc 0 00004FA2 C3 ret 206 207 f58_set_strategy: 0 00004FA3 B458 mov ah,MS_M_STRATEGY 0 00004FA5 881E[0000] mov [mem_strategy],bl 210 ; clc 0 00004FA9 C3 ret 212 213 f58_get_link: 0 00004FAA B458 mov ah,MS_M_STRATEGY 0 00004FAC A0[0000] mov al,[dmd_upper_link] 216 ; clc 0 00004FAF C3 ret 218 219 f58_set_link: 0 00004FB0 B8FFFF mov ax,ED_FUNCTION ; return function not implemented 0 00004FB3 8B0E[0000] mov cx,[dmd_upper_root] ; if no upper memory chain 0 00004FB7 41 inc cx ; CX = FFFF 0 00004FB8 F9 stc 0 00004FB9 E328 jcxz f58_set_link20 0 00004FBB 49 dec cx 0 00004FBC 881E[0000] mov [dmd_upper_link],bl ; set link field 0 00004FC0 A1[0000] mov ax,[dmd_root] ; now find dmd before upper memory root 0 00004FC3 B24D mov dl,IDM ; assume we want to link 0 00004FC5 84DB test bl,bl ; do we want to link/unlink UMBs? 0 00004FC7 7502 jnz f58_set_link10 0 00004FC9 B25A mov dl,IDZ ; no, we want to unlink 232 f58_set_link10: 0 00004FCB 8EC0 mov es,ax ; point to DMD 0 00004FCD E86E01 call check_dmd_id ; stop if id is invalid 0 00004FD0 7211 jc f58_set_link20 ; and return an error 0 00004FD2 06 push es 0 00004FD3 E8FB00 call next_dmd ; does the next DMD match our 0 00004FD6 07 pop es 0 00004FD7 39C8 cmp ax,cx ; upper memory chain ? 0 00004FD9 75F0 jne f58_set_link10 0 00004FDB 2688160000 mov [es:DMD_ID],dl ; set appropriate link type 0 00004FE0 B80358 mov ax,(MS_M_STRATEGY*256)+3; return AX unchanged 243 ; clc 244 f58_set_link20: 0 00004FE3 C3 ret 246 247 248 249 250 ;**************************************** 251 ;* * 252 ;* Memory Function Subroutines * 253 ;* * 254 ;**************************************** 255 ; 256 ; FREE_ALL takes the PSP passed in the BX register and free's all 257 ; memory associated with that PSP. 258 ; 259 ; entry: bx = requested PSP 260 ; 261 ; exit: 262 ; 263 Public free_all 264 free_all: 0 00004FE4 8E06[0000] mov es,[dmd_root] ; es -> first dmd 266 267 free_all_loop: 0 00004FE8 E85301 call check_dmd_id ; if block is invalid 0 00004FEB 722B jc free_all_fail ; then quit now 270 0 00004FED 88C2 mov dl,al ; dl = id code 0 00004FEF 26391E0100 cmp [es:DMD_PSP],bx ; if block is owned by another 0 00004FF4 7506 jnz free_all_next ; then check next 274 0 00004FF6 268326010000 and word [es:DMD_PSP],0 ; Free this partition 276 free_all_next: 0 00004FFC 06 push es 0 00004FFD E8D100 call next_dmd ; es -> next block up 0 00005000 58 pop ax 0 00005001 80FA4D cmp dl,IDM ; if previous block wasn't last 0 00005004 74E2 jz free_all_loop ; then keep going 0 00005006 3906[0000] cmp [dmd_upper_root],ax 0 0000500A 760A jbe free_all_end 0 0000500C A1[0000] mov ax,[dmd_upper_root] ; free UMBs as well 0 0000500F 83F8FF cmp ax,-1 ; if UMB head is valid 0 00005012 8EC0 mov es,ax 0 00005014 75D2 jne free_all_loop 288 free_all_end: 0 00005016 31C0 xor ax,ax ; Otherwise Stop 290 291 free_all_fail: 0 00005018 C3 ret 293 294 ; 295 ; SET_OWNER allows the OWNING PSP to specify the new owner of 296 ; the partition. An error is returned if an incorrect partition address 297 ; is given or the partition is not owned by the current PSP. 298 ; 299 ; Entry:- AX == New PSP 300 ; BX == Partition Start 301 ; 302 ; Exit:- 303 ; no carry AX == Unknown 304 ; carry AX == Error Code 305 ; 306 Public set_owner 307 set_owner: 0 00005019 06 push es 0 0000501A 4B dec bx 0 0000501B 8EC3 mov es,bx ; ES points at DMD (We Hope) 0 0000501D 93 xchg ax,bx ; Save the New PSP address in BX 0 0000501E E81D01 call check_dmd_id ; Check for a valid DMD 0 00005021 7215 jc s_o20 0 00005023 A1[0000] mov ax,[current_psp] 0 00005026 263B060100 cmp ax,[es:DMD_PSP] ; Check the Current PSP owns the memory 0 0000502B 7507 jnz s_o10 0 0000502D 26891E0100 mov [es:DMD_PSP],bx ; Set the new owner and return 0 00005032 EB04 jmp s_o20 319 320 s_o10: 0 00005034 B8F7FF mov ax,ED_BLOCK 0 00005037 F9 stc 323 s_o20: 0 00005038 07 pop es 0 00005039 C3 ret 326 327 ; 328 ; Search for a free memory block at least as big as bx 329 ; entry: bx = requested size 330 ; success exit: cf clear, es -> dmd 331 ; cx = block size 332 ; failure exit: cf set, ax = error code 333 ; cx = biggest block available 334 335 search_mem: 0 0000503A B8F9FF mov ax,ED_DMD ; assume bad DMD chain 0 0000503D 8B0E[0000] mov cx,[dmd_root] ; start at the bottom 0 00005041 E374 jcxz search_mem_exit 0 00005043 8EC1 mov es,cx ; lets clean up memory list 0 00005045 800E[0000]04 or byte [mem_strategy],FIRST_FIT ; grab 1st block we come to 341 search_mem_init: 0 0000504A 31F6 xor si,si ; si = max mem available 0 0000504C BFFFFF mov di,0FFFFh ; di = size of candiate (FFFF=none) 344 ; dx = dmd of candidate 345 search_mem_loop: 0 0000504F E8EC00 call check_dmd_id ; if block is invalid 0 00005052 7263 jc search_mem_exit ; then quit now 348 0 00005054 26833E010000 cmp word [es:DMD_PSP],0 ; if block is owned 0 0000505A 752F jnz search_mem_next ; then check another 351 0 0000505C E87D00 call merge_mem ; group with unallocated blocks 353 0 0000505F 8CC0 mov ax,es ; AX = current DMD 0 00005061 268B0E0300 mov cx,[es:DMD_LEN] ; cx = block length 356 0 00005066 39F1 cmp cx,si ; is it the biggest block we 0 00005068 7202 jb search_mem40 ; have found so far ? 0 0000506A 89CE mov si,cx ; if so then save the new size 360 search_mem40: 361 0 0000506C 39D9 cmp cx,bx ; if it's not long enough 0 0000506E 721B jb search_mem_next ; then try the next block 364 0 00005070 F606[0000]06 test byte [mem_strategy],FIRST_FIT+LAST_FIT 0 00005075 750B jnz search_mem50 ; grab this block ? 367 0 00005077 F606[0000]01 test byte [mem_strategy],BEST_FIT ; if BEST FIT then we only save this 0 0000507C 740D jz search_mem_next ; candidate if the previous 0 0000507E 39F9 cmp cx,di ; candidate was bigger 0 00005080 7309 jae search_mem_next 372 search_mem50: 0 00005082 8CC2 mov dx,es ; save this DMD candidate 0 00005084 89CF mov di,cx ; along with it's length 0 00005086 8026[0000]FB and byte [mem_strategy],~ FIRST_FIT 376 search_mem_next: 0 0000508B E83B00 call search_next_dmd ; try for another DMD 0 0000508E B8F8FF mov ax,ED_MEMORY ; assume insufficient mem 0 00005091 7224 jc search_mem_exit ; stop if it's true 380 0 00005093 8CC0 mov ax,es 0 00005095 3B06[0000] cmp ax,[dmd_upper_root] ; if we reach the dmd upper root 0 00005099 75B4 jne search_mem_loop ; then we have a special case 0 0000509B F606[0000]C0 test byte [mem_strategy],UPPER_FIT+UPPER_ONLY_FIT ; upper memory block preferred or explicitly requested? 0 000050A0 7507 jnz search_mem_next10 ; then also search UMBs 0 000050A2 83FFFF cmp di,0FFFFh ; no block found in lower mem? 0 000050A5 7402 je search_mem_next10 ; then also search UMBs 0 000050A7 EB0E jmp search_mem_exit ; else return the previously found block 389 search_mem_next10: 0 000050A9 800E[0000]04 or byte [mem_strategy],FIRST_FIT ; grab 1st high memory block we find 0 000050AE F606[0000]40 test byte [mem_strategy],UPPER_ONLY_FIT 0 000050B3 7595 jnz search_mem_init ; upper only is another special case 0 000050B5 EB98 jmp search_mem_loop 394 395 search_mem_exit: 0 000050B7 8026[0000]FB and byte [mem_strategy],~ FIRST_FIT 0 000050BC 89F9 mov cx,di ; DX&DI contain our best candidate 0 000050BE 47 inc di ; if DI=FFFF then we don't have one 0 000050BF 7404 je search_mem_bad ; else we return with CX = size 0 000050C1 8EC2 mov es,dx ; and ES = DMD 0 000050C3 F8 clc ; clear the error flag 0 000050C4 C3 ret 403 404 search_mem_bad: 0 000050C5 89F1 mov cx,si ; no allocation made, so return 406 search_mem_error: ; biggest block and flag the error 0 000050C7 F9 stc 0 000050C8 C3 ret 409 410 search_next_dmd: 411 ; On Entry: 412 ; ES = current DMD 413 ; On Exit: 414 ; ES = AX = next DMD 415 ; DX/DI preserved 416 ; 0 000050C9 26803E00004D cmp byte [es:DMD_ID],IDM ; do we have any more blocks ? 0 000050CF 75F6 jne search_mem_error ; no, return CY set 419 ; jmp next_dmd ; else try next DMD 420 421 ; Point to next DOS Memory Descriptor (dmd) in the chain 422 ; entry: es -> current dmd 423 ; exit: es -> next dmd 424 425 next_dmd: 0 000050D1 8CC0 mov ax,es 0 000050D3 2603060300 add ax,[es:DMD_LEN] 0 000050D8 40 inc ax ; allow for dmd itself 0 000050D9 8EC0 mov es,ax 0 000050DB C3 ret 431 432 ; Increase the size of the current mem block 433 ; by gobbling all adjacent unallocated blocks 434 ; entry: es -> dmd 435 ; exit: cf = 1, al = 7 if chain is broken 436 ; ES,SI,DI,DX,BX preserved 437 438 merge_mem: 0 000050DC 06 push es 0 000050DD 26803E00004D cmp byte [es:DMD_ID],IDM ; if no more dmd's 0 000050E3 7522 jnz merge_mem_done ; then just quit 442 0 000050E5 E8E9FF call next_dmd 0 000050E8 E85300 call check_dmd_id ; if id is invalid 0 000050EB 721B jc merge_mem_quit ; then return an error 446 0 000050ED 26833E010000 cmp word [es:DMD_PSP],0 ; if next dmd is owned 0 000050F3 7512 jnz merge_mem_done ; then done 449 0 000050F5 268B0E0300 mov cx,[es:DMD_LEN] ; if free, grab its length 0 000050FA 07 pop es ; restore base dmd 452 0 000050FB 26A20000 mov [es:DMD_ID],al ; use next's id (in case of last) 0 000050FF 41 inc cx 0 00005100 26010E0300 add [es:DMD_LEN],cx ; add new memory to base 0 00005105 EBD5 jmp merge_mem ; and try again 457 458 merge_mem_done: 0 00005107 F8 clc ; clear error flag 460 merge_mem_quit: 0 00005108 07 pop es ; restore base dmd 0 00005109 C3 ret ; with cf and error flag 463 464 465 ; If needed, create a new dmd on top of allocated memory 466 ; entry: es -> current block 467 ; bx = requested block size 468 ; cx = current block size 469 470 make_dmd: 0 0000510A 39CB cmp bx,cx ; if request and size match 0 0000510C 7427 jz make_dmd_done ; then that's all we need 473 0 0000510E 268A160000 mov dl,[es:DMD_ID] ; get current block id 0 00005113 26891E0300 mov [es:DMD_LEN],bx ; else shrink this block 0 00005118 26C60600004D mov byte [es:DMD_ID],IDM ; not the last now 0 0000511E E8B0FF call next_dmd 0 00005121 2688160000 mov [es:DMD_ID],dl ; our old id for the new dmd 0 00005126 26C70601000000 mov word [es:DMD_PSP],0 ; new block is free 0 0000512D 29D9 sub cx,bx 0 0000512F 49 dec cx 0 00005130 26890E0300 mov [es:DMD_LEN],cx ; length is whatever is left 483 484 make_dmd_done: 0 00005135 C3 ret 486 487 ; Get passed value of memory block 488 ; exit: es -> dmd 489 ; al = DMD_ID, cf cleared if valid 490 ; al = 7, cf set if invalid 491 492 get_dmd: 0 00005136 E8[0000] call reload_ES 0 00005139 8CC0 mov ax,es 0 0000513B 48 dec ax ; back up to dmd 0 0000513C 8EC0 mov es,ax 497 ; jmp check_dmd_id ; fall through 498 499 ; Check first byte in the dmd for a valid id code 500 ; entry: es -> dmd 501 ; exit: al = DMD_ID, cf cleared if valid 502 ; al = 7, cf set if invalid 503 504 Public check_dmd_id 505 506 check_dmd_id: 0 0000513E 26A00000 mov al,[es:DMD_ID] 0 00005142 3C4D cmp al,IDM ; if not last 0 00005144 7408 jz check_dmd_done ; then good 0 00005146 3C5A cmp al,IDZ ; if last 0 00005148 7404 jz check_dmd_done ; also good 512 0 0000514A B8F7FF mov ax,ED_BLOCK ; Invalid DMD 514 check_dmd_error: 0 0000514D F9 stc ; flag the error 516 check_dmd_done: 0 0000514E C3 ret 518 519 PCM_CODE ends 520 === Switch to base=00C180h -> "PCMODE_DATA" 521 section PCMODE_DATA public align=2 class=DATA 522 523 extrn lock_tables:dword 524 extrn unlock_tables:dword 525 526 extrn dmd_address:word ; don't free DMD's with segment under this value 527 extrn dmd_owner:word ; don't free DMD's with owner under this value 528 extrn dmd_upper_root:word 529 extrn dmd_upper_link:byte 530 extrn current_psp:word 531 extrn locus:byte 532 extrn mem_strategy:byte 533 extrn dmd_root:word 534 535 PCMODE_DATA ends 536 537 end === Trace listing source: drdos/bin/error.lst 1 ; File : $ERROR.ASM$ 2 ; 3 ; Description : 4 ; 5 ; Original Author : DIGITAL RESEARCH 6 ; 7 ; Last Edited By : $CALDERA$ 8 ; 9 ;-----------------------------------------------------------------------; 10 ; Copyright Work of Caldera, Inc. All Rights Reserved. 11 ; 12 ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, 13 ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. 14 ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES 15 ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF 16 ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO 17 ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE 18 ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE 19 ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, 20 ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, 21 ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, 22 ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF 23 ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT 24 ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND 25 ; CIVIL LIABILITY. 26 ;-----------------------------------------------------------------------; 27 ; 28 ; *** Current Edit History *** 29 ; *** End of Current Edit History *** 30 ; $Log$ 31 ; ERROR.A86 1.17 94/12/02 11:01:03 32 ; added logical error entry 33 ; ERROR.A86 1.16 93/11/26 15:51:29 34 ; Update char_error so ES:SI -> device driver header itself 35 ; ERROR.A86 1.14 93/09/09 22:36:26 36 ; Int 21/59 uses error stack (for benefit of Lantastic) 37 ; ERROR.A86 1.13 93/09/03 20:28:11 38 ; Add "no critical errors" support (int 21/6C) 39 ; ENDLOG 40 ; 41 ; This file contains the Error handling routines for PCMODE 42 ; When a function encounters an error it jumps to the ERROR_EXIT 43 ; function which will process the error consistantly. FCB_ERROR_EXIT 44 ; is a special case of ERROR_EXIT where the error code is not returned 45 ; directly to the user but is still saved for func59 46 ; 47 48 group PCMDATA PCMODE_DATA FDOS_DSEG 49 group PCMCODE PCM_CODE PCM_RODATA 50 51 ASSUME DS:PCMDATA 52 53 %include "pcmode.mac" 1 <1> ; File : $PCMODE.EQU$ 2 <1> ; 3 <1> ; Description : 4 <1> ; 5 <1> ; Original Author : DIGITAL RESEARCH 6 <1> ; 7 <1> ; Last Edited By : $CALDERA$ 8 <1> ; 9 <1> ;-----------------------------------------------------------------------; 10 <1> ; Copyright Work of Caldera, Inc. All Rights Reserved. 11 <1> ; 12 <1> ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, 13 <1> ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. 14 <1> ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES 15 <1> ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF 16 <1> ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO 17 <1> ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE 18 <1> ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE 19 <1> ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, 20 <1> ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, 21 <1> ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, 22 <1> ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF 23 <1> ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT 24 <1> ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND 25 <1> ; CIVIL LIABILITY. 26 <1> ;-----------------------------------------------------------------------; 27 <1> ; 28 <1> ; *** Current Edit History *** 29 <1> ; *** End of Current Edit History *** 30 <1> ; 31 <1> ; $Log$ 32 <1> ; 33 <1> ; ENDLOG 34 <1> ; This file contains all the general purpose definitions 35 <1> ; and equates used by the PCMODE Module. 36 <1> ; 37 <1> 38 <1> TRUE equ 0FFFFh ; value of TRUE 39 <1> FALSE equ 0 ; value of FALSE 40 <1> 41 <1> ;TRUE_VERSION equ 0107h 42 <1> 43 <1> IDLE_DETECT equ TRUE ; Check for IDLE Process's 44 <1> 45 <1> %if IDLE_DETECT 46 <1> IDLE_COMMAND equ 0001h ; Command Processor Active 47 <1> IDLE_DOSFUNC equ 0002h ; DOS Function Called 48 <1> IDLE_INT28 equ 0004h ; INT 28 Called 49 <1> 50 <1> IDLE_ON equ 4000h ; ReSet when Idle Checking Enabled 51 <1> IDLE_INIT equ 8000h ; ReSet when $IDLE$ Loaded and Active 52 <1> IDLE_DISABLE equ IDLE_INIT + IDLE_ON 53 <1> 54 <1> PROC_IDLE equ 0001 ; Process is IDLE 55 <1> PROC_INT28 equ 0002 ; INT28 Polling Loop 56 <1> PROC_KEYIN equ 0003 ; Keyboard Input 57 <1> PROC_DEVIN equ 0004 ; Device Input Routine 58 <1> %endif 59 <1> 60 <1> 61 <1> STACK_SIZE equ 192 ; Local Stack Size (Levels) 62 <1> MAX_PATHLEN equ 80 ; Maximum Path length 63 <1> MAX_FILELEN equ 13 64 <1> 65 <1> ; 66 <1> ; DOS process termination Codes 67 <1> ; 68 <1> TERM_NORMAL equ 0 ; Normal Termination 69 <1> TERM_BREAK equ 1 ; Termination by Control Break 70 <1> TERM_ERROR equ 2 ; Termination by Critical Error 71 <1> TERM_RESIDENT equ 3 ; Terminate and Stay Resident 72 <1> 73 <1> ; 74 <1> ; Critical Error responses from the default INT 24 handler and 75 <1> ; the DO_INT24 routine. 76 <1> ; 77 <1> ERR_IGNORE equ 0 ; Ignore Error 78 <1> ERR_RETRY equ 1 ; Retry the Operation 79 <1> ERR_ABORT equ 2 ; Terminate the Process 80 <1> ERR_FAIL equ 3 ; Fail Function 81 <1> ; 82 <1> OK_FAIL equ 00001000b ; Fail is a Valid Response 83 <1> OK_RETRY equ 00010000b ; Retry is a Valid Response 84 <1> OK_IGNORE equ 00100000b ; Ignore is a valid Response 85 <1> OK_RIF equ 00111000b ; All Responsese are Valid 86 <1> OK_RI equ 00110000b ; Retry and Ignore are Valid 87 <1> OK_RF equ 00011000b ; Retry and Fail are Valid 88 <1> ; 89 <1> NO_CRIT_ERRORS equ 01000000b ; critical error shouldn't be generated 90 <1> ; warning - must match FDOS.A86 91 <1> ; 92 <1> ; The following equates define the format in which the users registers 93 <1> ; are saved on the stack. This format is also seen by an application 94 <1> ; when a critical error occurs. 95 <1> ; 96 <1> %macro POP_DOS 0.nolist ; Pop User Registers a la MS-DOS 97 <1> pop ax 98 <1> pop bx 99 <1> pop cx 100 <1> pop dx 101 <1> pop si 102 <1> pop di 103 <1> pop bp 104 <1> pop ds 105 <1> pop es 106 <1> %endmacro 107 <1> 108 <1> %macro PUSH_DOS 0.nolist ; Push User Registers 109 <1> push es 110 <1> push ds 111 <1> push bp 112 <1> push di 113 <1> push si 114 <1> push dx 115 <1> push cx 116 <1> push bx 117 <1> push ax 118 <1> %endmacro 119 <1> 120 <1> 121 <1> labelsize reg_AX, word, 00 122 <1> labelsize reg_AL, byte, 00 123 <1> labelsize reg_AH, byte, 01 124 <1> 125 <1> labelsize reg_BX, word, 02 126 <1> labelsize reg_BL, byte, 02 127 <1> labelsize reg_BH, byte, 03 128 <1> 129 <1> labelsize reg_CX, word, 04 130 <1> labelsize reg_CL, byte, 04 131 <1> labelsize reg_CH, byte, 05 132 <1> 133 <1> labelsize reg_DX, word, 06 134 <1> labelsize reg_DL, byte, 06 135 <1> labelsize reg_DH, byte, 07 136 <1> 137 <1> labelsize reg_SI, word, 08 138 <1> labelsize reg_DI, word, 10 139 <1> labelsize reg_BP, word, 12 140 <1> 141 <1> labelsize reg_DS, word, 14 142 <1> labelsize reg_ES, word, 16 143 <1> 144 <1> labelsize reg_IP, word, 18 145 <1> labelsize reg_CS, word, 20 146 <1> labelsize reg_FLAGS, word, 22 147 <1> 148 <1> ; Processor Flags 149 <1> CARRY_FLAG equ 0001h ; Carry Flag 150 <1> ZERO_FLAG equ 0040h ; Zero Flag 151 <1> SIGN_FLAG equ 0080h ; Sign Flag 152 <1> INT_FLAG equ 0200h ; Interrupt Flag 153 <1> DIR_FLAG equ 0400h ; Direction Flag 154 <1> OFLW_FLAG equ 0800h ; OverFlow Flag 155 <1> 156 <1> labelsize DMD_ID, byte, 0 ; id code ('M' or 'Z') 157 <1> labelsize DMD_PSP, word, 1 ; owner of memory block 158 <1> labelsize DMD_LEN, word, 3 ; length of memory block 159 <1> labelsize DMD_IDLE_FLAGS, word, 6 ; idle flags live here 160 <1> labelsize DMD_NAME, byte, 8 ; ASCIIZ name field 161 <1> DMD_NAME_LEN equ 8 ; 8 Bytes long 162 <1> IDM equ 'M' ; not last id code 163 <1> IDZ equ 'Z' ; last id code 164 <1> 165 <1> ;PCMCODE GROUP PCM_HEADER, PCM_CODE, BDOS_CODE, PCM_RODATA 166 <1> ;PCMCODE GROUP PCM_HISTORY, PCM_ICODE, PCM_CODEND 167 <1> 168 <1> ;PCM_HEADER CSEG PARA 169 <1> ;PCM_CODE CSEG BYTE 170 <1> ;PCM_RODATA CSEG WORD 171 <1> ;BDOS_CODE CSEG WORD 172 <1> ;PCM_HISTORY CSEG BYTE 173 <1> ;PCM_ICODE CSEG BYTE 174 <1> ;PCM_CODEND CSEG PARA 175 <1> 176 <1> 177 <1> ;PCMDATA GROUP PCMODE_DATA, FDOS_DSEG, FIXED_DOS_DATA 178 <1> ;PCMDATA GROUP PCMODE_CODE, GLOBAL_DATA, BDOS_DATA, PCMODE_DSIZE 179 <1> 180 <1> ;PCMODE_DATA DSEG WORD ; DOS Data 181 <1> ;FDOS_DSEG DSEG WORD COMMON ; FDOS Parameter Block 182 <1> === Switch to base=00C180h -> "FDOS_DSEG" 183 <1> section FDOS_DSEG common align=2 class=DATA === Switch to base=00C180h -> "FDOS_DSEG" 184 <1> section FDOS_DSEG 185 00000000 <1> fdos_data dw 7 dup (?) === Switch to base=00C180h -> "FDOS_DSEG" 186 <1> FDOS_DSEG ends 187 <1> 188 <1> ;FIXED_DOS_DATA CSEG WORD 'DATA' ; Fixed DOS Data Area 189 <1> ;PCMODE_CODE CSEG WORD 'DATA' ; DATA relative CODE 190 <1> ;GLOBAL_DATA DSEG WORD ; GLOBAL DOS DATA (Process Independant) 191 <1> ;BDOS_DATA DSEG WORD ; BDOS Data Area 192 <1> ;PCMODE_DSIZE DSEG PARA ; End of DOS Data Area 54 %include "fdosdef.mac" 1 <1> ; File : $FDOS.DEF$ 2 <1> ; 3 <1> ; Description : 4 <1> ; 5 <1> ; Original Author : DIGITAL RESEARCH 6 <1> ; 7 <1> ; Last Edited By : $CALDERA$ 8 <1> ; 9 <1> ;-----------------------------------------------------------------------; 10 <1> ; Copyright Work of Caldera, Inc. All Rights Reserved. 11 <1> ; 12 <1> ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, 13 <1> ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. 14 <1> ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES 15 <1> ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF 16 <1> ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO 17 <1> ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE 18 <1> ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE 19 <1> ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, 20 <1> ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, 21 <1> ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, 22 <1> ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF 23 <1> ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT 24 <1> ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND 25 <1> ; CIVIL LIABILITY. 26 <1> ;-----------------------------------------------------------------------; 27 <1> ; 28 <1> ; *** Current Edit History *** 29 <1> ; *** End of Current Edit History *** 30 <1> ; 31 <1> ; $Log$ 32 <1> ; 33 <1> ; ENDLOG 34 <1> 35 <1> FD_DISKINFO equ 48h 36 <1> FD_FLUSH equ 49h 37 <1> FD_SELECT equ 4Ah 38 <1> FD_EXEC equ 4Bh 39 <1> FD_EXIT equ 4Ch 40 <1> FD_FCB equ 4Dh 41 <1> FD_COMMIT equ 50H 42 <1> FD_NEW equ 51h 43 <1> FD_LOCK equ 52h 44 <1> FD_DDIO equ 54h 45 <1> FD_EXPAND equ 55h 46 <1> FD_REOPEN equ 58h 47 <1> 48 <1> FDOS_MAXPARM equ 7 ; Maximum FDOS Parameter Length (WORDS) 49 <1> 50 <1> FD_FUNC equ fdos_data 51 <1> 52 <1> FD_DRIVE equ fdos_data + 2 53 <1> labelsize FD_DPB, dword, fdos_data + 4 54 <1> FD_DPBOFF equ fdos_data + 4 55 <1> FD_DPBSEG equ fdos_data + 6 56 <1> FD_ADJUST equ fdos_data + 8 57 <1> 58 <1> labelsize FD_NAME, dword, fdos_data + 2 59 <1> FD_NAMEOFF equ fdos_data + 2 60 <1> FD_NAMESEG equ fdos_data + 4 61 <1> 62 <1> FD_MODE equ fdos_data + 6 63 <1> 64 <1> FD_HANDLE equ fdos_data + 2 65 <1> 66 <1> labelsize FD_BUF, dword, fdos_data + 4 67 <1> FD_BUFOFF equ fdos_data + 4 68 <1> FD_BUFSEG equ fdos_data + 6 69 <1> 70 <1> FD_COUNT equ fdos_data + 8 71 <1> 72 <1> labelsize FD_OFFSET, dword, fdos_data + 4 73 <1> 74 <1> FD_METHOD equ fdos_data + 8 75 <1> 76 <1> FD_FLAG equ fdos_data + 6 77 <1> 78 <1> FD_ATTRIB equ fdos_data + 8 79 <1> 80 <1> labelsize FD_PATH, dword, fdos_data + 4 81 <1> FD_PATHOFF equ fdos_data + 4 82 <1> FD_PATHSEG equ fdos_data + 6 83 <1> 84 <1> labelsize FD_ONAME, dword, fdos_data + 2 85 <1> FD_ONAMEOFF equ fdos_data + 2 86 <1> FD_ONAMESEG equ fdos_data + 4 87 <1> 88 <1> labelsize FD_NNAME, dword, fdos_data + 10 89 <1> FD_NNAMEOFF equ fdos_data + 10 90 <1> FD_NNAMESEG equ fdos_data + 12 91 <1> 92 <1> FD_SFLAG equ fdos_data + 4 93 <1> FD_DATE equ fdos_data + 6 94 <1> FD_TIME equ fdos_data + 8 95 <1> 96 <1> labelsize FD_LENGTH, dword, fdos_data + 8 97 <1> labelsize FD_LFLAG, word, fdos_data + 12 98 <1> 99 <1> FD_NEWHND equ fdos_data + 4 100 <1> 101 <1> labelsize FD_FCBADR, dword, fdos_data + 2 102 <1> FD_FCBOFF equ fdos_data + 2 103 <1> FD_FCBSEG equ fdos_data + 4 104 <1> 105 <1> FD_FCBCNT equ fdos_data + 6 106 <1> FD_FCBFUNC equ fdos_data + 8 107 <1> 108 <1> FD_PSPSEG equ fdos_data + 2 109 <1> 110 <1> FD_BPBOFF equ fdos_data + 2 111 <1> FD_BPBSEG equ fdos_data + 4 112 <1> FD_DDSCOFF equ fdos_data + 6 113 <1> FD_DDSCSEG equ fdos_data + 8 114 <1> FD_SIG1 equ fdos_data + 10 115 <1> FD_SIG2 equ fdos_data + 12 116 <1> 117 <1> FD_IOCTLFUNC equ fdos_data + 4 118 <1> FD_IOCTLSTAT equ fdos_data + 6 119 <1> 120 <1> FD_NUMOPEN equ fdos_data + 2 121 <1> 122 <1> FD_DDIO_DRV_OP equ fdos_data + 2 123 <1> FD_DDIO_NSECTORS equ fdos_data + 4 124 <1> FD_DDIO_STARTLOW equ fdos_data + 6 125 <1> FD_DDIO_STARTHIGH equ fdos_data + 8 126 <1> FD_DDIO_DMAOFF equ fdos_data + 10 127 <1> FD_DDIO_DMASEG equ fdos_data + 12 128 <1> 129 <1> FD_LFNSEARCH equ fdos_data + 10 55 %include "msdos.mac" 1 <1> ; File : $MSDOS.EQU$ 2 <1> ; 3 <1> ; Description : 4 <1> ; 5 <1> ; Original Author : DIGITAL RESEARCH 6 <1> ; 7 <1> ; Last Edited By : $CALDERA$ 8 <1> ; 9 <1> ;-----------------------------------------------------------------------; 10 <1> ; Copyright Work of Caldera, Inc. All Rights Reserved. 11 <1> ; 12 <1> ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, 13 <1> ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. 14 <1> ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES 15 <1> ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF 16 <1> ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO 17 <1> ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE 18 <1> ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE 19 <1> ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, 20 <1> ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, 21 <1> ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, 22 <1> ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF 23 <1> ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT 24 <1> ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND 25 <1> ; CIVIL LIABILITY. 26 <1> ;-----------------------------------------------------------------------; 27 <1> ; 28 <1> ; *** Current Edit History *** 29 <1> ; *** End of Current Edit History *** 30 <1> ; 31 <1> ; $Log$ 32 <1> ; 33 <1> ; ENDLOG 34 <1> 35 <1> 36 <1> MS_P_TERMCPM equ 00H 37 <1> MS_C_READ equ 01H 38 <1> MS_C_WRITE equ 02H 39 <1> MS_A_READ equ 03H 40 <1> MS_A_WRITE equ 04H 41 <1> MS_L_WRITE equ 05H 42 <1> MS_C_RAWIO equ 06H 43 <1> MS_C_RAWIN equ 07H 44 <1> MS_C_NOECHO equ 08H 45 <1> MS_C_WRITESTR equ 09H 46 <1> MS_C_READSTR equ 0aH 47 <1> MS_C_STAT equ 0bH 48 <1> MS_C_FLUSH equ 0cH 49 <1> MS_DRV_ALLRESET equ 0dH 50 <1> MS_DRV_SET equ 0eH 51 <1> MS_F_OPEN equ 0fH 52 <1> MS_F_CLOSE equ 10H 53 <1> MS_F_SFIRST equ 11H 54 <1> MS_F_SNEXT equ 12H 55 <1> MS_F_DELETE equ 13H 56 <1> MS_F_READ equ 14H 57 <1> MS_F_WRITE equ 15H 58 <1> MS_F_MAKE equ 16H 59 <1> MS_F_RENAME equ 17H 60 <1> MS_DRV_GET equ 19H 61 <1> MS_F_DMAOFF equ 1aH 62 <1> MS_DRV_ALLOC equ 1bH 63 <1> MS_DRV_ALLOCSPEC equ 1cH 64 <1> MS_F_READRAND equ 21H 65 <1> MS_F_WRITERAND equ 22H 66 <1> MS_F_SIZE equ 23H 67 <1> MS_F_RANDREC equ 24H 68 <1> MS_S_SETINT equ 25H 69 <1> MS_P_MKPSP equ 26H 70 <1> MS_F_READBLK equ 27H 71 <1> MS_F_WRITEBLK equ 28H 72 <1> MS_F_PARSE equ 29H 73 <1> MS_T_GETDATE equ 2aH 74 <1> MS_T_SETDATE equ 2bH 75 <1> MS_T_GETTIME equ 2cH 76 <1> MS_T_SETTIME equ 2dH 77 <1> MS_F_VERIFY equ 2eH 78 <1> MS_F_DMAGET equ 2fH 79 <1> MS_S_BDOSVER equ 30H 80 <1> MS_P_TERMKEEP equ 31H 81 <1> MS_S_BREAK equ 33H 82 <1> MS_S_GETINT equ 35H 83 <1> MS_DRV_SPACE equ 36H 84 <1> MS_S_COUNTRY equ 38H 85 <1> MS_X_MKDIR equ 39H 86 <1> MS_X_RMDIR equ 3aH 87 <1> MS_X_CHDIR equ 3bH 88 <1> MS_X_CREAT equ 3cH 89 <1> MS_X_OPEN equ 3dH 90 <1> MS_X_CLOSE equ 3eH 91 <1> MS_X_READ equ 3fH 92 <1> MS_X_WRITE equ 40H 93 <1> MS_X_UNLINK equ 41H 94 <1> MS_X_LSEEK equ 42H 95 <1> MS_X_CHMOD equ 43H 96 <1> MS_X_IOCTL equ 44H 97 <1> MS_X_DUP equ 45H 98 <1> MS_X_DUP2 equ 46H 99 <1> MS_X_CURDIR equ 47H 100 <1> MS_M_ALLOC equ 48H 101 <1> MS_M_FREE equ 49H 102 <1> MS_M_SETBLOCK equ 4aH 103 <1> MS_X_EXEC equ 4bH 104 <1> MS_X_EXIT equ 4cH 105 <1> MS_X_WAIT equ 4dH 106 <1> MS_X_FIRST equ 4eH 107 <1> MS_X_NEXT equ 4fH 108 <1> MS_P_SETPSP equ 50H 109 <1> MS_F_GETVERIFY equ 54H 110 <1> MS_X_RENAME equ 56H 111 <1> MS_X_DATETIME equ 57H 112 <1> MS_M_STRATEGY equ 58h 113 <1> MS_F_ERROR equ 59H 114 <1> MS_X_MKTEMP equ 5aH 115 <1> MS_X_MKNEW equ 5bH 116 <1> MS_F_LOCK equ 5cH 117 <1> MS_X_EXPAND equ 60H 118 <1> MS_P_GETPSP equ 62H 119 <1> MS_X_GETCP equ 6601h 120 <1> MS_X_SETCP equ 6602h 121 <1> MS_X_SETHC equ 67h 122 <1> MS_X_COMMIT equ 68h 123 <1> 124 <1> DOS_INT equ 21h ; DOS Entry Point 125 <1> ; 126 <1> STDIN equ 0 ; Standard Console Input Handle 127 <1> STDOUT equ 1 ; Standard Console Output Handle 128 <1> STDERR equ 2 ; Standard Error Output 129 <1> STDAUX equ 3 ; Auxilary Device Handle 130 <1> STDPRN equ 4 ; Printer Device Handle 56 %include "mserror.mac" 1 <1> ; File : $MSERROR.EQU$ 2 <1> ; 3 <1> ; Description : 4 <1> ; 5 <1> ; Original Author : DIGITAL RESEARCH 6 <1> ; 7 <1> ; Last Edited By : $CALDERA$ 8 <1> ; 9 <1> ;-----------------------------------------------------------------------; 10 <1> ; Copyright Work of Caldera, Inc. All Rights Reserved. 11 <1> ; 12 <1> ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, 13 <1> ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. 14 <1> ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES 15 <1> ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF 16 <1> ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO 17 <1> ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE 18 <1> ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE 19 <1> ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, 20 <1> ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, 21 <1> ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, 22 <1> ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF 23 <1> ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT 24 <1> ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND 25 <1> ; CIVIL LIABILITY. 26 <1> ;-----------------------------------------------------------------------; 27 <1> ; 28 <1> ; *** Current Edit History *** 29 <1> ; *** End of Current Edit History *** 30 <1> ; 31 <1> ; $Log$ 32 <1> ; 33 <1> ; ENDLOG 34 <1> 35 <1> ED_FUNCTION equ -01 ; invalid function number 36 <1> ED_FILE equ -02 ; file not found 37 <1> ED_PATH equ -03 ; path not found 38 <1> ED_HANDLE equ -04 ; too many open files 39 <1> ED_ACCESS equ -05 ; file access denied 40 <1> ED_H_MATCH equ -06 ; invalid handle number 41 <1> ED_DMD equ -07 ; memory descriptor destroyed 42 <1> ED_MEMORY equ -08 ; insufficient memory 43 <1> ED_BLOCK equ -09 ; invalid memory block addr 44 <1> ED_ENVIRON equ -10 ; invalid environment 45 <1> ED_FORMAT equ -11 ; invalid format 46 <1> ED_ACC_CODE equ -12 ; invalid access code 47 <1> ED_DATA equ -13 ; invalid data 48 <1> ED_DRIVE equ -15 ; invalid drive specified 49 <1> ED_DIR equ -16 ; can't remove current dir 50 <1> ED_DEVICE equ -17 ; not same device 51 <1> ED_ROOM equ -18 ; no more files 52 <1> 53 <1> ED_PROTECT equ -19 ; disk write protected 54 <1> ED_BADUNIT equ -20 ; invalid drive specified 55 <1> ED_NOTREADY equ -21 ; drive doesn't respond 56 <1> ED_BADCMD equ -22 ; invalid command to driver 57 <1> ED_BADDATA equ -23 ; data CRC error 58 <1> ED_BADRHLEN equ -24 ; (shouldn't happen) 59 <1> ED_BADSEEK equ -25 ; can't seek to track 60 <1> ED_BADMEDIA equ -26 ; unrecognizable medium 61 <1> ED_RNF equ -27 ; record/sector not found 62 <1> ED_NOPAPER equ -28 ; printer error 63 <1> ED_WRFAIL equ -29 ; write failed 64 <1> ED_RDFAIL equ -30 ; read failed 65 <1> ED_GENFAIL equ -31 ; anything failed 66 <1> ED_SHAREFAIL equ -32 ; sharing conflict 67 <1> ED_LOCKFAIL equ -33 ; locking conflict 68 <1> ED_DISKCHG equ -34 ; invalid disk change 69 <1> ED_NOFCBS equ -35 ; FCB table exhausted 70 <1> ED_NOLOCKS equ -36 ; lock list items exhausted 71 <1> ED_NET equ -50 ; Network Request Not Supported 72 <1> 73 <1> ED_NETACCESS equ -65 ; file access denied 74 <1> 75 <1> ED_NETPWD equ -73 ; Server Password Error 76 <1> ED_NETVER equ -74 ; Incorrect Server version 77 <1> ED_NETREQ equ -75 ; No Local Network Resources 78 <1> ED_NETTIME equ -76 ; Network Time Out Error 79 <1> ED_NETCOMM equ -77 ; Network Communications Error 80 <1> ED_NETSRVR equ -78 ; No Server Network Resources 81 <1> ED_NETLOG equ -79 ; Server Not Logged In 82 <1> 83 <1> ED_EXISTS equ -80 ; file already exists 84 <1> ED_MAKE equ -82 ; Cannot Make (Files ??) 85 <1> ED_FAIL equ -83 ; FAIL code returned from INT 24 86 <1> ED_STRUCT equ -84 ; Out of Structures 87 <1> ED_ASSIGN equ -85 ; Already Assigned 88 <1> ED_PASSWORD equ -86 ; Invalid Password 89 <1> ED_PARAM equ -87 ; Invalid Parameter 90 <1> ED_NETWRITE equ -88 ; Network write fault 91 <1> ED_NETFUNC equ -89 ; Function not supported on network 92 <1> ED_COMPONENT equ -90 ; system component not installed 93 <1> ED_LASTERROR equ -90 ; Last Error Number Used 94 <1> 95 <1> 96 <1> CLASS_RESOURCE equ 1 ; Out of Resource 97 <1> CLASS_TEMP equ 2 ; Temporary Situation 98 <1> CLASS_AUTHOR equ 3 ; Authorization Error 99 <1> CLASS_INTERNAL equ 4 ; Internal System Software Error 100 <1> CLASS_HARDWARE equ 5 ; Hardware Failure 101 <1> CLASS_SYSTEM equ 6 ; Serious System Failure 102 <1> CLASS_APPLIC equ 7 ; Application Program Error 103 <1> CLASS_LOST equ 8 ; File/Item Not Found 104 <1> CLASS_FORMAT equ 9 ; File/Item Illegal Format 105 <1> CLASS_LOCKED equ 10 ; File/Item Locked 106 <1> CLASS_MEDIA equ 11 ; Media Failure 107 <1> CLASS_EXISTS equ 12 ; Item Already Exists 108 <1> CLASS_UNKNOWN equ 13 ; Unknown Classification 109 <1> 110 <1> ACT_RETRY equ 1 ; Retry a few times then prompt user 111 <1> ACT_DELAY equ 2 ; Delay then as ACT_RETRY 112 <1> ACT_USER equ 3 ; Prompt user to re-enter data 113 <1> ACT_ABORT equ 4 ; Clean Up then ABORT the process 114 <1> ACT_TERM equ 5 ; Terminate immeadiately NO CLEAN UP 115 <1> ACT_IGNORE equ 6 ; Ignore the Error 116 <1> ACT_URETRY equ 7 ; Retry the error after user intervention 117 <1> 118 <1> LOC_UNKNOWN equ 1 ; Unknown error location 119 <1> LOC_BLOCK equ 2 ; Block Device Failure 120 <1> LOC_NET equ 3 ; Network Failure 121 <1> LOC_CHAR equ 4 ; Related to Serial/Character devices 122 <1> LOC_MEMORY equ 5 ; Failure related to Memory 57 %include "psp.mac" 1 <1> ; File : $PSP.DEF$ 2 <1> ; 3 <1> ; Description : 4 <1> ; 5 <1> ; Original Author : DIGITAL RESEARCH 6 <1> ; 7 <1> ; Last Edited By : $CALDERA$ 8 <1> ; 9 <1> ;-----------------------------------------------------------------------; 10 <1> ; Copyright Work of Caldera, Inc. All Rights Reserved. 11 <1> ; 12 <1> ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, 13 <1> ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. 14 <1> ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES 15 <1> ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF 16 <1> ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO 17 <1> ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE 18 <1> ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE 19 <1> ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, 20 <1> ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, 21 <1> ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, 22 <1> ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF 23 <1> ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT 24 <1> ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND 25 <1> ; CIVIL LIABILITY. 26 <1> ;-----------------------------------------------------------------------; 27 <1> ; 28 <1> ; *** Current Edit History *** 29 <1> ; *** End of Current Edit History *** 30 <1> ; 31 <1> ; $Log$ 32 <1> ; 33 <1> ; ENDLOG 34 <1> ; 35 <1> ; Program Segment Prefix 36 <1> ; ---------------------- 37 <1> ; This structure holds vital information for DOS programs 38 <1> ; 39 <1> ;******************************************************************************* 40 <1> ;* 41 <1> ;* +-----+-----+-----+-----+-----+-----+-----+-----+ 42 <1> ;* 00 | int 20 | memory | *** | jmpf|longjmp off| 43 <1> ;* +-----+-----+-----+-----+-----+-----+-----+-----+ 44 <1> ;* 08 |longjmp seg| int22 Off | int22 Seg | int22 Off | 45 <1> ;* +-----+-----+-----+-----+-----+-----+-----+-----+ 46 <1> ;* 10 | int22 Seg | int24 Off | int24 Seg | Parent | 47 <1> ;* +-----+-----+-----+-----+-----+-----+-----+-----+ 48 <1> ;* 18 | Default Handle Table | 49 <1> ;* +-----+-----+-----+-----+-----+-----+-----+-----+ 50 <1> ;* 20 | XFT (20 entries) | 51 <1> ;* +-----+-----+-----+-----+-----+-----+-----+-----+ 52 <1> ;* 28 | XFT contd. | Environ | User SP | 53 <1> ;* +-----+-----+-----+-----+-----+-----+-----+-----+ 54 <1> ;* 30 | User SS | xfnmax | xftoff | xftseg | 55 <1> ;* +-----+-----+-----+-----+-----+-----+-----+-----+ 56 <1> ;* 38 | res1 | res2 | ric | *** | ********* | 57 <1> ;* +-----+-----+-----+-----+-----+-----+-----+-----+ 58 <1> ;* 40 | version | ********* | ********* | ********* | 59 <1> ;* +-----+-----+-----+-----+-----+-----+-----+-----+ 60 <1> ;* 48 | ********* | ********* | ********* | ********* | 61 <1> ;* +-----+-----+-----+-----+-----+-----+-----+-----+ 62 <1> ;* 50 | int 21 | retf| *** | ********* | ********* | 63 <1> ;* +-----+-----+-----+-----+-----+-----+-----+-----+ 64 <1> ;* 58 | ********* | ********* | PSP fcb 1 | 65 <1> ;* +-----+-----+-----+-----+-----+-----+-----+-----+ 66 <1> 67 <1> labelsize PSP_INT20, word, 0000h 68 <1> labelsize PSP_MEMORY, word, 0002h 69 <1> ;PSP_??? equ byte ptr 0004h 70 <1> labelsize PSP_LONGCALL, byte, 0005h 71 <1> labelsize PSP_LONGOFF, word, 0006h 72 <1> labelsize PSP_LONGSEG, word, 0008h 73 <1> labelsize PSP_TERM_IP, word, 000Ah 74 <1> labelsize PSP_TERM_CS, word, 000Ch 75 <1> labelsize PSP_BREAK_IP, word, 000Eh 76 <1> labelsize PSP_BREAK_CS, word, 0010h 77 <1> labelsize PSP_ERROR_IP, word, 0012h 78 <1> labelsize PSP_ERROR_CS, word, 0014h 79 <1> labelsize PSP_PARENT, word, 0016h 80 <1> labelsize PSP_XFT, byte, 0018h 81 <1> ; 82 <1> ; The Default Handle Table is HERE !! 83 <1> ; 84 <1> labelsize PSP_ENVIRON, word, 002ch 85 <1> labelsize PSP_USERSP, word, 002eh 86 <1> labelsize PSP_USERSS, word, 0030h 87 <1> labelsize PSP_XFNMAX, word, 0032h 88 <1> labelsize PSP_XFTPTR, dword, 0034h 89 <1> labelsize PSP_XFTOFF, word, 0034h 90 <1> labelsize PSP_XFTSEG, word, 0036h 91 <1> labelsize PSP_RES1, word, 0038h ; DOS Reserved 0FFFFh 92 <1> labelsize PSP_RES2, word, 003Ah ; DOS Reserved 0FFFFh 93 <1> labelsize PSP_RIC, byte, 003Ch ; Return Interim Character flag 94 <1> labelsize PSP_VERSION, word, 0040h ; DOS version number 95 <1> 96 <1> 97 <1> labelsize PSP_DOSCALL, word, 0050h 98 <1> labelsize PSP_DOSRETF, byte, 0052h 99 <1> 100 <1> labelsize PSP_FCB1, byte, 005Ch 101 <1> labelsize PSP_FCB2, byte, 006Ch 102 <1> labelsize PSP_COMLEN, byte, 0080h 103 <1> labelsize PSP_COMLINE, byte, 0081h 104 <1> 105 <1> XFNMAX equ 20 106 <1> 107 <1> PSPLEN equ 100h 108 <1> PSPILEN equ 60h 58 %include "char.mac" 1 <1> ; File : $CHAR.DEF$ 2 <1> ; 3 <1> ; Description : 4 <1> ; 5 <1> ; Original Author : DIGITAL RESEARCH 6 <1> ; 7 <1> ; Last Edited By : $CALDERA$ 8 <1> ; 9 <1> ;-----------------------------------------------------------------------; 10 <1> ; Copyright Work of Caldera, Inc. All Rights Reserved. 11 <1> ; 12 <1> ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, 13 <1> ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. 14 <1> ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES 15 <1> ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF 16 <1> ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO 17 <1> ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE 18 <1> ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE 19 <1> ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, 20 <1> ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, 21 <1> ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, 22 <1> ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF 23 <1> ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT 24 <1> ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND 25 <1> ; CIVIL LIABILITY. 26 <1> ;-----------------------------------------------------------------------; 27 <1> ; 28 <1> ; *** Current Edit History *** 29 <1> ; *** End of Current Edit History *** 30 <1> ; 31 <1> ; $Log$ 32 <1> ; 33 <1> ; ENDLOG 34 <1> ;************************************************; 35 <1> ;* *; 36 <1> ;* Character Definitions *; 37 <1> ;* *; 38 <1> ;************************************************; 39 <1> 40 <1> CTLA equ 'A' - '@' 41 <1> CTLB equ 'B' - '@' 42 <1> CTLC equ 'C' - '@' 43 <1> CTLD equ 'D' - '@' 44 <1> CTLE equ 'E' - '@' 45 <1> CTLF equ 'F' - '@' 46 <1> CTLG equ 'G' - '@' 47 <1> BELL equ 'G' - '@' 48 <1> CTLH equ 'H' - '@' 49 <1> CTLI equ 'I' - '@' 50 <1> TAB equ 'I' - '@' 51 <1> CTLJ equ 'J' - '@' 52 <1> LF equ 'J' - '@' 53 <1> CTLK equ 'K' - '@' 54 <1> CTLM equ 'M' - '@' 55 <1> CR equ 'M' - '@' 56 <1> CTLP equ 'P' - '@' 57 <1> CTLQ equ 'Q' - '@' 58 <1> CTLR equ 'R' - '@' 59 <1> CTLS equ 'S' - '@' 60 <1> CTLT equ 'T' - '@' 61 <1> CTLU equ 'U' - '@' 62 <1> CTLV equ 'V' - '@' 63 <1> CTLW equ 'W' - '@' 64 <1> CTLX equ 'X' - '@' 65 <1> CTLY equ 'Y' - '@' 66 <1> CTLZ equ 'Z' - '@' 67 <1> ESC equ '[' - '@' 68 <1> CTLBS equ '\' - '@' 69 <1> CTLUB equ '_' - '@' 70 <1> CTLUP equ '^' - '@' 71 <1> DEL equ 07Fh 72 <1> RUBOUT equ DEL 73 <1> 74 <1> CTL equ '^' 59 %include "request.mac" 1 <1> ; File : $REQUEST.EQU$ 2 <1> ; 3 <1> ; Description : 4 <1> ; 5 <1> ; Original Author : DIGITAL RESEARCH 6 <1> ; 7 <1> ; Last Edited By : $CALDERA$ 8 <1> ; 9 <1> ;-----------------------------------------------------------------------; 10 <1> ; Copyright Work of Caldera, Inc. All Rights Reserved. 11 <1> ; 12 <1> ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, 13 <1> ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. 14 <1> ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES 15 <1> ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF 16 <1> ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO 17 <1> ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE 18 <1> ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE 19 <1> ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, 20 <1> ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, 21 <1> ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, 22 <1> ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF 23 <1> ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT 24 <1> ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND 25 <1> ; CIVIL LIABILITY. 26 <1> ;-----------------------------------------------------------------------; 27 <1> ; 28 <1> ; *** Current Edit History *** 29 <1> ; *** End of Current Edit History *** 30 <1> ; 31 <1> ; $Log$ 32 <1> ; ENDLOG 33 <1> 34 <1> 35 <1> P_DSTRUC struc 0 000003A2 ???? dw ? 0 000003A4 ???????? REQUEST dd ? 0 000003A8 ???????? DMA dd ? 39 <1> P_DSTRUC ends 40 <1> 41 <1> P_STRUC struc 0 000003A2 ???? dw ? ; saved BP 0 000003A4 ???? REQUEST_OFF dw ? ; request header offset 0 000003A6 ???? REQUEST_SEG dw ? ; request header segment 0 000003A8 ???? DMAOFF dw ? ; transfer offset 0 000003AA ???? DMASEG dw ? ; transfer segment 0 000003AC ?? RETRY db ? ; retry count for disk errors 0 000003AD ?? DIRECT db ? ; 0 if DMA deblocking required 0 000003AE ?? ROSCMD db ? ; 2 = read, 3 = write, 4 = verify 0 000003AF ?? SETTLE db ? ; for fast settle on reads 0 000003B0 ?? SECTOR db ? ; sector # (0..BPB_SPT-1) 0 000003B1 ?? HEAD db ? ; head # (0..BPB_HEADS-1) 0 000003B2 ???? CYL dw ? ; cylinder # (0..1023) 0 000003B4 ???? COUNT dw ? ; requested sector count 0 000003B6 ???? MCNT dw ? ; physical sector count 0 000003B8 ???????? LBABLOCK dd ? ; Logical Block Address of start sector 57 <1> P_STRUC ends 58 <1> 59 <1> 60 <1> 61 <1> CMD_INIT equ 0 ; Initialize the Device Driver 62 <1> CMD_MEDIA_CHECK equ 1 ; Request Media Check 63 <1> CMD_BUILD_BPB equ 2 ; Build Drive BPB 64 <1> CMD_INPUT_IOCTL equ 3 ; IOCTL input 65 <1> CMD_INPUT equ 4 ; Input 66 <1> CMD_INPUT_NOWAIT equ 5 ; Non destructive input no wait 67 <1> CMD_INPUT_STATUS equ 6 ; Input status 68 <1> CMD_INPUT_FLUSH equ 7 ; Input flush 69 <1> CMD_OUTPUT equ 8 ; Output 70 <1> CMD_OUTPUT_VERIFY equ 9 ; Output with verify 71 <1> CMD_OUTPUT_STATUS equ 10 ; Output status 72 <1> CMD_OUTPUT_FLUSH equ 11 ; Output flush 73 <1> CMD_OUTPUT_IOCTL equ 12 ; IOCTL output 74 <1> CMD_DEVICE_OPEN equ 13 ; Device OPEN 75 <1> CMD_DEVICE_CLOSE equ 14 ; Device CLOSE 76 <1> CMD_FIXED_MEDIA equ 15 ; Removeable Media Check 77 <1> CMD_GENERIC_IOCTL equ 19 ; Generic IOCTL 78 <1> CMD_GET_DEVICE equ 23 ; Get the Logical Device 79 <1> CMD_SET_DEVICE equ 24 ; Set the Logical Device 80 <1> CMD_QUERY_IOCTL equ 25 ; query ioctl support 81 <1> 82 <1> ; Generic Request Header Format 83 <1> 84 <1> labelsize RH_LEN, byte, 0 85 <1> labelsize RH_UNIT, byte, 1 86 <1> labelsize RH_CMD, byte, 2 87 <1> labelsize RH_STATUS, word, 3 88 <1> RHS_DONE equ 0100h 89 <1> RHS_BUSY equ 0200h 90 <1> RHS_IC equ 0400h ; Interim Character 91 <1> RHS_RM equ 0800h 92 <1> RHS_ERROR equ 8000h 93 <1> 94 <1> ;****** 95 <1> ;* No longer safe to use - some device drivers trample on them.... 96 <1> ;* 97 <1> ;* RH_STRATEGY equ dword ptr 5 ; Device Strategy Routine 98 <1> ;* RH_STRATOFF equ word ptr 5 ; Strategy Offset 99 <1> ;* RH_STRATSEG equ word ptr 7 ; Strategy Segment 100 <1> ;* RH_INTERRUPT equ dword ptr 9 ; Device Interrupt Routine 101 <1> ;* RH_INTOFF equ word ptr 9 ; Intterupt Offset 102 <1> ;* RH_INTSEG equ word ptr 11 ; Interrupt Segment 103 <1> ;***** 104 <1> 105 <1> ; Request header for initialization 106 <1> 107 <1> labelsize RH0_NUNITS, byte, 13 108 <1> labelsize RH0_RESIDENT, word, 14 109 <1> labelsize RH0_BPBOFF, word, 18 110 <1> labelsize RH0_BPBSEG, word, 20 111 <1> labelsize RH0_DRIVE, byte, 22 112 <1> RH0_LEN equ 22 113 <1> 114 <1> ; Request header for media check 115 <1> 116 <1> labelsize RH1_MEDIA, byte, 13 ; BDOS: current media byte 117 <1> labelsize RH1_RETURN, byte, 14 ; driver: return code (00, 01, FF) 118 <1> labelsize RH1_VOLID, dword, 15 ; driver: volume label address 119 <1> RH1_LEN equ 15 120 <1> 121 <1> ; Request header for "build BPB" 122 <1> 123 <1> labelsize RH2_MEDIA, byte, 13 ; BDOS or driver? 124 <1> labelsize RH2_BUFFER, dword, 14 ; BDOS: scratch buffer for driver use 125 <1> labelsize RH2_BPB, dword, 18 ; same as the following: 126 <1> labelsize RH2_BPBOFF, word, 18 ; driver: address of new BPB 127 <1> labelsize RH2_BPBSEG, word, 20 128 <1> RH2_LEN equ 24 129 <1> 130 <1> ; Request header for input/output 131 <1> 132 <1> labelsize RH4_MEDIA, byte, 13 ; BDOS: current media byte 133 <1> labelsize RH4_RIC, byte, 13 ; BDOS: Return Interim Char flg 134 <1> labelsize RH4_BUFFER, dword, 14 ; BDOS: disk transfer address 135 <1> labelsize RH4_BUFOFF, word, 14 ; BDOS: Buffer Offset 136 <1> labelsize RH4_BUFSEG, word, 16 ; BDOS: Buffer Segment 137 <1> labelsize RH4_COUNT, word, 18 ; BDOS: sector count 138 <1> labelsize RH4_SECTOR, word, 20 ; BDOS: starting sector 139 <1> labelsize RH4_VOLID, dword, 22 ; driver: volume if illegal disk change 140 <1> labelsize RH4_BIGSECTOR, dword, 26 141 <1> labelsize RH4_BIGSECTORLO, word, 26 142 <1> labelsize RH4_BIGSECTORHI, word, 28 143 <1> 144 <1> RH4_LEN equ 30 145 <1> RH4_CDEV_LEN equ 22 146 <1> 147 <1> ; Request Header for Non-Destructive Input 148 <1> 149 <1> labelsize RH5_CHAR, byte, 13 ; Character Read from Device 150 <1> labelsize RH5_RIC, byte, 13 ; BDOS: Return Interim Char flg 151 <1> RH5_LEN equ 14 152 <1> 153 <1> ; Request Header for Device Open 154 <1> 155 <1> RH13_LEN equ 13 156 <1> 157 <1> ; Request Header for Device Close 158 <1> 159 <1> RH14_LEN equ 13 160 <1> 161 <1> RH15_LEN equ 13 162 <1> 163 <1> ; Request header for generic IOCTL 164 <1> 165 <1> labelsize RH19_CATEGORY, word, 13 ; BDOS: major/minor function number 166 <1> labelsize RH19_MAJOR, byte, 13 ; BDOS: Major Function Number 167 <1> labelsize RH19_MINOR, byte, 14 ; BDOS: Minor Function Number 168 <1> labelsize RH19_SI, word, 15 ; BDOS: User SI 169 <1> labelsize RH19_DI, word, 17 ; BDOS: User DI 170 <1> labelsize RH19_GENPB, dword, 19 ; BDOS: extra parameters 171 <1> RH19_LEN equ 23 172 <1> 173 <1> RQ19_SET equ 40h ; set device parameters 174 <1> RQ19_GET equ 60h ; get device parameters 175 <1> RQ19_WRITE equ 41h ; write tracks 176 <1> RQ19_READ equ 61h ; read tracks 177 <1> RQ19_FORMAT equ 42h ; format tracks 178 <1> RQ19_VERIFY equ 62h ; verify tracks 179 <1> RQ19_SETMEDIA equ 46h ; set media ID 180 <1> RQ19_GETMEDIA equ 66h ; get media ID 181 <1> RQ19_LOCKLOG equ 4ah 182 <1> RQ19_LOCKPHYS equ 4bh 183 <1> RQ19_UNLOCKLOG equ 6ah 184 <1> RQ19_UNLOCKPHYS equ 6bh 185 <1> 186 <1> RQ19_PRP_START equ 4Ch ; start of codepage prepare 187 <1> RQ19_PRP_END equ 4Dh ; end of codepage prepare 188 <1> RQ19_SELECT equ 4Ah ; select code page 189 <1> RQ19_QRY_SEL equ 6Ah ; query selected code page 190 <1> RQ19_QRY_PRP equ 6Bh ; query prepared code page(s) 191 <1> RQ19_DSP_SET equ 5Fh ; set display information 192 <1> RQ19_DSP_GET equ 7Fh ; get display information 193 <1> 194 <1> ; Request header for get/set drive 195 <1> 196 <1> labelsize RH24_CMD, byte, 14 ; BDOS: Command Code 197 <1> labelsize RH24_STATUS, word, 15 ; BDOS: Status 198 <1> labelsize RH24_RESVD, dword, 17 ; BDOS: Reserved 199 <1> RH24_LEN equ 21 200 <1> 201 <1> RH_SIZE equ 30 ; maximum size of request header 60 61 ; 62 labelsize ERR_TBL_CODE, byte, 0 ; Error Code in Table 63 labelsize ERR_TBL_CLASS, byte, 1 ; Error Class entry in Table 64 labelsize ERR_TBL_ACTION, byte, 2 ; Error Action entry in Table 65 labelsize ERR_TBL_LOCUS, byte, 3 ; Locus entry in table 66 ERR_TBL_LEN equ 4 ; 4 bytes per entry 67 ; === Switch to base=000000h -> "PCM_CODE" 68 section PCM_CODE public align=1 class=CODE 69 extrn get_dseg:near 70 extrn do_int24:near 71 extrn reload_registers:near 72 extrn return_AX_CLC:near 73 ; 74 ; ***************************** 75 ; *** DOS Function 59 *** 76 ; *** Get Extended Error *** 77 ; ***************************** 78 ; 79 Public func59 80 81 func59: 0 0000514F C43E[0000] les di,[error_dev] ; Return device driver address 0 00005153 8A3E[0000] mov bh,[error_class] ; return the Error Class 0 00005157 8A1E[0000] mov bl,[error_action] ; the Action Code 0 0000515B 8A2E[0000] mov ch,[error_locus] ; the Locus Code 0 0000515F A1[0000] mov ax,[error_code] ; the Error Code 87 0 00005162 C536[0000] lds si,[int21regs_ptr] ; point to user stack 0 00005166 8C4410 mov [reg_ES + si],es 0 00005169 897C0A mov [reg_DI + si],di 0 0000516C 895C02 mov [reg_BX + si],bx 0 0000516F 894C04 mov [reg_CX + si],cx 0 00005172 16 push ss 0 00005173 1F pop ds 0 00005174 E9[0000] jmp return_AX_CLC 96 97 ; On Entry:- AX == Internal Error Number 98 ; 99 ; On Exit:- None 100 ; CY set if error should be returned 101 ; CY clear if it should be ignored 102 ; 103 Public error_exit 104 error_exit: 0 00005177 803E[0000]00 cmp byte [internal_flag],0 ; If this is an internal 0 0000517C 7506 jnz error_ret ; do not generate a critical 0 0000517E E86700 call disk_error ; error 0 00005181 7504 jnz error_r10 ; No Error Occured or Ignored 0 00005183 C3 ret ; in critcal error handler 110 111 ; 112 ; Return the error code to the user and DO NOT generate any 113 ; critical errors. 114 ; 115 ; On Entry:- AX == Internal Error Number 116 ; 117 ; On Exit:- None 118 ; 119 Public error_ret 120 error_ret: 0 00005184 E8D500 call set_error ; the internal error code 122 error_r10: ; otherwise negate 0 00005187 C43E[0000] les di,[int21regs_ptr] 0 0000518B 26834D1601 or word [es:reg_FLAGS + di],CARRY_FLAG ; set the "users" carry Flag 0 00005190 F9 stc ; also set real one 126 %if offset reg_AX EQ 0 0 00005191 AB stosw ; save return code 128 %else 129 mov [es:reg_AX + di],ax 130 %endif 0 00005192 C3 ret 132 133 ; 134 ; On Entry:- AX == Internal Error Number 135 ; 136 ; On Exit:- None 137 ; 138 Public fcberror_exit 139 fcberror_exit: 0 00005193 E85200 call disk_error ; Process the error code generating 0 00005196 7402 jz fe_e10 ; a critical error is required 0 00005198 B0FF mov al,0FFh ; on FCB error return AL = FF 143 fe_e10: 0 0000519A C3 ret 145 146 ; WARNING - may be called from FDOS with DS = SYSDAT 147 ; 148 ; CHAR_ERROR is called when any character device function generates 149 ; an error. First CHAR_ERROR sets the correct parameters for Get 150 ; Extended Error. Then it generates a Critical Error by calling 151 ; DO_INT24. 152 ; 153 ; Entry:- ES:SI -> device driver header 154 ; SS:BX -> RH_ 155 ; AX = RH_STATUS 156 ; 157 ; Exit AL Error Action 158 ; 159 Public char_error 160 char_error: 0 0000519B 36F606[0000]40 test byte [ss:valid_flg],NO_CRIT_ERRORS 0 000051A1 7403 jz char_e10 0 000051A3 B003 mov al,ERR_FAIL ; no critical errors allowed 0 000051A5 C3 ret ; so just fail things 165 char_e10: 0 000051A6 1E push ds 0 000051A7 06 push es 0 000051A8 53 push bx 0 000051A9 51 push cx 0 000051AA 52 push dx 0 000051AB 56 push si 0 000051AC 57 push di 0 000051AD 16 push ss 0 000051AE 1F pop ds ; DS -> our data now 0 000051AF 8936[0000] mov word ptr [error_dev+0],si ; save the device driver address 0 000051B3 8C06[0200] mov word ptr [error_dev+2],es ; and then initialise the FUNC59 0 000051B7 06 push es ; data areas 0 000051B8 83E07F and ax,007Fh ; Mask the Unused Bits 0 000051BB 80CCB8 or ah,80h+OK_RIF ; Retry/Ignore/Abort/Fail allowable 0 000051BE 36807F0208 cmp byte [ss:RH_CMD + bx],CMD_OUTPUT ; is this a read or write failure ? 0 000051C3 7502 jne char_e20 0 000051C5 FEC4 inc ah ; 01 is a Write Failure 183 char_e20: 0 000051C7 8826[0000] mov [rwmode],ah ; 0 000051CB 50 push ax ; save for int 24 0 000051CC 98 cbw ; zero AH again 0 000051CD F7D8 neg ax ; convert to an internal error 0 000051CF 83C0ED add ax,ED_PROTECT ; code for set_error 0 000051D2 B104 mov cl,LOC_CHAR 0 000051D4 E88500 call set_error 0 000051D7 83C0ED add ax,ED_PROTECT ; convert to hardware error 0 000051DA 97 xchg ax,di ; DI == hardware error 0 000051DB 58 pop ax 0 000051DC 07 pop es 0 000051DD E8[0000] call do_int24 ; execute INT 24 0 000051E0 5F pop di 0 000051E1 5E pop si 0 000051E2 5A pop dx 0 000051E3 59 pop cx 0 000051E4 5B pop bx 0 000051E5 07 pop es 0 000051E6 1F pop ds 0 000051E7 C3 ret 204 205 ; 206 ; DISK_ERROR gains control after any DOS disk based function 207 ; has been executed which generates an error. First ERROR set the 208 ; correct parameters for Get Extended Error. Then it determines if 209 ; the current error should generate a Critical Error and calls 210 ; DO_INT24 if TRUE. 211 ; 212 ; 213 ; On Entry: 214 ; AX Internal Error Code 215 ; 216 ; On Exit: 217 ; AX 0 if no error to return (Ignore) 218 ; AX DOS Error Code 219 ; ZF reflects AX 220 ; 221 disk_error: 0 000051E8 B104 mov cl,LOC_CHAR ; assume character device 223 ; determine if the error is 0 000051EA F606[0000]80 test byte [rwmode],80h ; caused by a character or 0 000051EF 7502 jnz disk_e10 ; block device and set the 0 000051F1 B102 mov cl,LOC_BLOCK ; the critical error locus 227 disk_e10: 0 000051F3 E86600 call set_error ; record error information 0 000051F6 7461 jz disk_e50 ; just return a logical error. 230 0 000051F8 83C0ED add ax,ED_PROTECT ; Convert to HardWare Error 0 000051FB 89C7 mov di,ax ; DI == HardWare Error 233 ; Now get the information 0 000051FD 8A26[0000] mov ah,[rwmode] ; about the error location 235 0 00005201 80E4C7 and ah,~ OK_RIF ; mask the all responses 237 ; mov al,valid_flg ; valid flag contains no crit 238 ; and al,not NO_CRITICAL_ERRORS ; errors bit, but if that was 239 ; or ah,al ; set we wouldn't be here 0 00005204 0A26[0000] or ah,[valid_flg] ; or in valid responses 241 0 00005208 83FBE1 cmp bx,ED_GENFAIL ; if it's general failure 0 0000520B 7503 jne disk_e20 ; we cannot Ignore the error 0 0000520D 80E4DF and ah,~ OK_IGNORE ; but must Abort/Fail/Retry 245 disk_e20: ; as appropriate 246 0 00005210 A0[0000] mov al,[err_drv] ; get the failing drive 0 00005213 A2[0000] mov [error_drive],al ; and save locally 249 0 00005216 C436[0000] les si,[error_dev] ; get device driver header 251 252 ; are we are a character device 0 0000521A F6C480 test ah,80h ; as these have handled at a 0 0000521D 7529 jnz disk_e40 ; lower level and just need 255 ; to be FAILed back to caller 256 0 0000521F E8[0000] call do_int24 ; Execute INT 24 258 0 00005222 88C3 mov bl,al ; Copy reponse into BL 260 0 00005224 31C0 xor ax,ax ; Assume Ignore Error 0 00005226 80FB00 cmp bl,ERR_IGNORE 0 00005229 742E jz disk_e50 ; Ignore the Error 264 0 0000522B 80FB03 cmp bl,ERR_FAIL 0 0000522E 7418 jz disk_e40 ; If not FAIL then RETRY 0 00005230 E8[0000] call reload_registers ; get back entry registers 0 00005233 A3[0000] mov [FD_FUNC],ax ; save AX for a moment 0 00005236 88E0 mov al,ah ; set up function number 0 00005238 30E4 xor ah,ah ; in AX 0 0000523A 8706[0000] xchg ax,[FD_FUNC] ; save for use by FDOS 0 0000523E 30E4 xor ah,ah ; zero AH 'cause it's handy 0 00005240 8B26[0000] mov sp,[retry_sp] ; Must be RETRY so reset the 0 00005244 FF26[0000] jmp near [retry_off] ; STACK and IP 275 276 disk_e40: 277 ; 278 ; When a Critical Error is FAILED then we do the following 279 ; if (extended error_code <= ED_SHAREFAIL) then 280 ; ret = ED_ACCESS; 281 ; else 282 ; ret = ED_FAIL; 283 ; extended error_code = ED_FAIL; 284 ; return(ret); 285 ; 286 ; nb. above proto-code is at the request of ant 287 ; 0 00005248 B85300 mov ax,-(ED_FAIL) ; always return ED_FAIL in the 0 0000524B 8706[0000] xchg ax,[error_code] ; extended error_code 0 0000524F 83F820 cmp ax,-(ED_SHAREFAIL) ; did we FAIL on sharing conflict ? 0 00005252 B80500 mov ax,-(ED_ACCESS) ; assume we did and prepare to return 0 00005255 7302 jae disk_e50 ; ED_ACCESS 0 00005257 B053 mov al,-(ED_FAIL) ; woops, return ED_FAIL after all 294 disk_e50: 0 00005259 09C0 or ax,ax ; NZ if error return required 0 0000525B C3 ret 297 298 ; 299 ; On Entry:- AX Internal Error Code 300 ; CL Critical Error Locus 301 ; 302 ; On Exit:- AX DOS Error Code 303 ; BX Internal Error Code 304 ; ZF set on logical error 305 set_error: 0 0000525C 89C3 mov bx,ax ; by default we return the raw error 0 0000525E BF[7400] mov di,offset critical_error; Scan for critical Errors First 0 00005261 E88600 call scan_error_table ; look for a matching error 0 00005264 723B jc set_logical_error 0 00005266 880E[0000] mov [locus],cl ; Save the critical error LOCUS 0 0000526A 83F8E0 cmp ax,ED_SHAREFAIL ; watch out for SHAREFAIL - the action 0 0000526D 7514 jne set_e10 ; depends on the caller 313 ; 314 ; ED_SHAREFAIL will return ED_ACCESS if the result of an attempt to open 315 ; a file in shared mode, otherwise (FCB's and compatibility) it will 316 ; generate a critical error. 317 ; 0 0000526F BBE1FF mov bx,ED_GENFAIL ; assume we want a critical error 0 00005272 833E[0000]3D cmp word [FD_FUNC],MS_X_OPEN ; is it a shared open ? 0 00005277 7540 jnz set_error_data 0 00005279 F706[0600]7000 test word [FD_MODE],01110000b ; mode 0 0000527F 7438 jz set_error_data 0 00005281 EB1B jmp set_e30 ; return a logical "access denied" 324 325 set_e10: 0 00005283 83F8DF cmp ax,ED_LOCKFAIL ; have we a lockfail error ? 0 00005286 750C jne set_e20 328 ; 329 ; ED_LOCKFAIL returns ED_ACCESS if a lock attempt fails, but a critical error 330 ; on an attempt to read/write a locked region. 331 ; 0 00005288 833E[0000]52 cmp word [FD_FUNC],FD_LOCK ; was it a result of specific lock 0 0000528D 7412 je set_logical_error ; call ? yes, it's a logical error 0 0000528F BBE1FF mov bx,ED_GENFAIL ; no, generate a critical error 0 00005292 EB25 jmp set_error_data 336 337 set_e20: 0 00005294 F606[0000]40 test byte [valid_flg],NO_CRIT_ERRORS 0 00005299 741E jz set_error_data ; do we allow critical errors ? 0 0000529B B8FBFF mov ax,ED_ACCESS ; extended error code is Access Denied 341 set_e30: 0 0000529E BBFBFF mov bx,ED_ACCESS ; return access denied to caller 343 ; jmp set_logical_error 344 345 set_logical_error: 0 000052A1 31FF xor di,di 0 000052A3 893E[0000] mov word ptr [error_dev+0],di ; must be a logical error so force 0 000052A7 893E[0200] mov word ptr [error_dev+2],di ; the ERROR_DEV to 0000:0000 0 000052AB BF[0000] mov di,offset logical_error ; scan the Logical error table 0 000052AE E83900 call scan_error_table 0 000052B1 83F8BF cmp ax,ED_NETACCESS ; if it's a networked access denied 0 000052B4 7503 jne set_error_data ; turn it into ordinary one 0 000052B6 BBFBFF mov bx,ED_ACCESS ; return a logical "access denied" 354 ; jmp set_error_data 355 356 set_error_data: 357 ; On Entry: 358 ; AX = Internal Error Code for extended error 359 ; BX = Internal Error Code for returned error 360 ; CS:DI -> error table entry 361 ; On Exit: 362 ; AX = DOS Error Code 363 ; BX = Internal Error Code 364 ; ZF set on logical error 365 ; 0 000052B9 F7D8 neg ax 0 000052BB A3[0000] mov [error_code],ax ; Save the Error Code 0 000052BE 2E8A4501 mov al,[cs:ERR_TBL_CLASS + di] 0 000052C2 A2[0000] mov [error_class],al ; Save the Class 0 000052C5 2E8A4502 mov al,[cs:ERR_TBL_ACTION + di] 0 000052C9 A2[0000] mov [error_action],al ; Save the Action 0 000052CC 2E8A4503 mov al,[cs:ERR_TBL_LOCUS + di] ; Get the Locus 0 000052D0 A2[0000] mov [error_locus],al ; Save the Locus and then check 0 000052D3 84C0 test al,al ; if the function overrides 0 000052D5 7506 jnz set_d10 ; this value 0 000052D7 A0[0000] mov al,[locus] ; Get the Global Locus value 0 000052DA A2[0000] mov [error_locus],al ; set by the calling function 378 set_d10: ; and save for FUNC 59 0 000052DD 89D8 mov ax,bx ; Return to the caller with 0 000052DF F7D8 neg ax ; the DOS error code. 0 000052E1 8B3E[0000] mov di,word ptr [error_dev] ; set ZF if logical error 0 000052E5 0B3E[0200] or di,word ptr [error_dev+2] ; error_dev = 0:0 0 000052E9 C3 ret 384 385 scan_error_table: 0 000052EA 2E803D00 cmp byte [cs:ERR_TBL_CODE + di],0 0 000052EE 740A je scan_et10 ; Check for the end of the list 0 000052F0 2E3A05 cmp al,[cs:ERR_TBL_CODE + di] 0 000052F3 7406 je scan_et20 0 000052F5 83C704 add di,ERR_TBL_LEN 0 000052F8 EBF0 jmp scan_error_table 392 scan_et10: 0 000052FA F9 stc 394 scan_et20: 0 000052FB C3 ret 396 === Switch to base=00C180h -> "FDOS_DSEG" 397 PCM_CODE ends 398 === Switch to base=000000h -> "PCM_RODATA" 399 section PCM_RODATA public align=2 class=CODE 400 logical_error label byte 401 ; 402 ; Internal Code Error Class Error Action Error Locus 403 ; ============= =========== ============ =========== 0 0000B9D6 FF070400 db ED_FUNCTION, CLASS_APPLIC, ACT_ABORT, 00 0 0000B9DA FE080302 db ED_FILE, CLASS_LOST, ACT_USER, LOC_BLOCK 0 0000B9DE FD080302 db ED_PATH, CLASS_LOST, ACT_USER, LOC_BLOCK 0 0000B9E2 FC010401 db ED_HANDLE, CLASS_RESOURCE, ACT_ABORT, LOC_UNKNOWN 0 0000B9E6 FB030300 db ED_ACCESS, CLASS_AUTHOR, ACT_USER, 00 0 0000B9EA BF030300 db ED_NETACCESS, CLASS_AUTHOR, ACT_USER, 00 0 0000B9EE FA070401 db ED_H_MATCH, CLASS_APPLIC, ACT_ABORT, LOC_UNKNOWN 0 0000B9F2 F9070505 db ED_DMD, CLASS_APPLIC, ACT_TERM, LOC_MEMORY 0 0000B9F6 F8010405 db ED_MEMORY, CLASS_RESOURCE, ACT_ABORT, LOC_MEMORY 0 0000B9FA F7070405 db ED_BLOCK, CLASS_APPLIC, ACT_ABORT, LOC_MEMORY 0 0000B9FE F6070405 db ED_ENVIRON, CLASS_APPLIC, ACT_ABORT, LOC_MEMORY 0 0000BA02 F5090301 db ED_FORMAT, CLASS_FORMAT, ACT_USER, LOC_UNKNOWN 0 0000BA06 F4070401 db ED_ACC_CODE, CLASS_APPLIC, ACT_ABORT, LOC_UNKNOWN 0 0000BA0A F3090401 db ED_DATA, CLASS_FORMAT, ACT_ABORT, LOC_UNKNOWN 0 0000BA0E F1080302 db ED_DRIVE, CLASS_LOST, ACT_USER, LOC_BLOCK 0 0000BA12 F0030302 db ED_DIR, CLASS_AUTHOR, ACT_USER, LOC_BLOCK 0 0000BA16 EF0D0302 db ED_DEVICE, CLASS_UNKNOWN, ACT_USER, LOC_BLOCK 0 0000BA1A EE080302 db ED_ROOM, CLASS_LOST, ACT_USER, LOC_BLOCK 0 0000BA1E B00C0302 db ED_EXISTS, CLASS_EXISTS, ACT_USER, LOC_BLOCK 0 0000BA22 AC010400 db ED_STRUCT, CLASS_RESOURCE, ACT_ABORT, 00 0 0000BA26 AA030301 db ED_PASSWORD, CLASS_AUTHOR, ACT_USER, LOC_UNKNOWN 0 0000BA2A AE010402 db ED_MAKE, CLASS_RESOURCE, ACT_ABORT, LOC_BLOCK 426 ;; db ED_NET, CLASS_FORMAT, ACT_USER, LOC_NET 0 0000BA2E AB0C0303 db ED_ASSIGN, CLASS_EXISTS, ACT_USER, LOC_NET 0 0000BA32 A9090301 db ED_PARAM, CLASS_FORMAT, ACT_USER, LOC_UNKNOWN 0 0000BA36 AD0D0401 db ED_FAIL, CLASS_UNKNOWN, ACT_ABORT, LOC_UNKNOWN 0 0000BA3A E00A0202 db ED_SHAREFAIL, CLASS_LOCKED, ACT_DELAY, LOC_BLOCK 0 0000BA3E DF0A0202 db ED_LOCKFAIL, CLASS_LOCKED, ACT_DELAY, LOC_BLOCK 0 0000BA42 DC010405 db ED_NOLOCKS, CLASS_RESOURCE, ACT_ABORT, LOC_MEMORY 0 0000BA46 00060501 db 00, CLASS_SYSTEM, ACT_TERM, LOC_UNKNOWN 434 435 critical_error label byte 436 ; 437 ; Internal Code Error Class Error Action Error Locus 438 ; ============= =========== ============ =========== 0 0000BA4A ED0B0702 db ED_PROTECT, CLASS_MEDIA, ACT_URETRY, LOC_BLOCK 0 0000BA4E EC040501 db ED_BADUNIT, CLASS_INTERNAL, ACT_TERM, LOC_UNKNOWN 0 0000BA52 EB050700 db ED_NOTREADY, CLASS_HARDWARE, ACT_URETRY, 00 0 0000BA56 EA040501 db ED_BADCMD, CLASS_INTERNAL, ACT_TERM, LOC_UNKNOWN 0 0000BA5A E90B0402 db ED_BADDATA, CLASS_MEDIA, ACT_ABORT, LOC_BLOCK 0 0000BA5E E7050102 db ED_BADSEEK, CLASS_HARDWARE, ACT_RETRY, LOC_BLOCK 0 0000BA62 E60B0702 db ED_BADMEDIA, CLASS_MEDIA, ACT_URETRY, LOC_BLOCK 0 0000BA66 E50B0402 db ED_RNF, CLASS_MEDIA, ACT_ABORT, LOC_BLOCK 0 0000BA6A E4020704 db ED_NOPAPER, CLASS_TEMP, ACT_URETRY, LOC_CHAR 0 0000BA6E E3050400 db ED_WRFAIL, CLASS_HARDWARE, ACT_ABORT, 00 0 0000BA72 E2050400 db ED_RDFAIL, CLASS_HARDWARE, ACT_ABORT, 00 0 0000BA76 E10D0400 db ED_GENFAIL, CLASS_UNKNOWN, ACT_ABORT, 00 0 0000BA7A E00A0202 db ED_SHAREFAIL, CLASS_LOCKED, ACT_DELAY, LOC_BLOCK 0 0000BA7E DF0A0202 db ED_LOCKFAIL, CLASS_LOCKED, ACT_DELAY, LOC_BLOCK 0 0000BA82 DD070401 db ED_NOFCBS, CLASS_APPLIC, ACT_ABORT, LOC_UNKNOWN 454 455 default_error label byte 0 0000BA86 00060501 db 00, CLASS_SYSTEM, ACT_TERM, LOC_UNKNOWN 457 === Switch to base=00C180h -> "FDOS_DSEG" 458 PCM_RODATA ends 459 === Switch to base=00C180h -> "PCMODE_DATA" 460 section PCMODE_DATA public align=2 class=DATA 461 462 extrn indos_flag:byte 463 extrn internal_flag:byte 464 extrn int21regs_ptr:dword 465 extrn current_psp:word 466 extrn retry_off:word, retry_sp:word 467 extrn valid_flg:byte 468 extrn error_locus:byte ; Error Locus 469 extrn error_code:word ; DOS format error Code 470 extrn error_action:byte ; Error Action Code 471 extrn error_class:byte ; Error Class 472 extrn error_dev:dword ; Failing Device Header 473 extrn error_drive:byte ; Failing Disk Drive 474 extrn err_drv:byte 475 extrn locus:byte 476 extrn rwmode:byte 477 === Switch to base=00C180h -> "FDOS_DSEG" 478 PCMODE_DATA ends 479 480 end === Trace listing source: drdos/bin/process.lst 1 ; File : $PROCESS.ASM$ 2 ; 3 ; Description : 4 ; 5 ; Original Author : DIGITAL RESEARCH 6 ; 7 ; Last Edited By : $CALDERA$ 8 ; 9 ;-----------------------------------------------------------------------; 10 ; Copyright Work of Caldera, Inc. All Rights Reserved. 11 ; 12 ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, 13 ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. 14 ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES 15 ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF 16 ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO 17 ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE 18 ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE 19 ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, 20 ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, 21 ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, 22 ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF 23 ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT 24 ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND 25 ; CIVIL LIABILITY. 26 ;-----------------------------------------------------------------------; 27 ; 28 ; *** Current Edit History *** 29 ; *** End of Current Edit History *** 30 ; $Log$ 31 ; PROCESS.A86 1.25 94/07/13 16:15:27 32 ; Int21/26 (create PSP) copies 1st 20 entries of parental XFT 33 ; PROCESS.A86 1.24 94/06/28 11:15:28 34 ; Don't issue an int 21 to get curret psp while within int21/4B load overlay 35 ; PROCESS.A86 1.20 93/09/28 19:44:03 36 ; Don't lose 8th character of name in DMD during exec 37 ; PROCESS.A86 1.14 93/06/18 21:00:57 38 ; Support for Int 21/4B05 added 39 ; PROCESS.A86 1.13 93/06/11 02:11:20 40 ; GateA20 disabled on EXEC for EXEPACKED apps 41 ; Fix termination code 42 ; ENDLOG 43 ; 44 45 group PCMDATA PCMODE_DATA FDOS_DSEG BDOS_DATA 46 group PCMCODE PCM_CODE 47 48 ASSUME DS:PCMDATA 49 50 [list -] 62 63 HILOAD equ TRUE 64 === Switch to base=000000h -> "PCM_CODE" 65 section PCM_CODE public align=1 class=CODE 66 extrn check_dmd_id:near 67 extrn dbcs_lead:near 68 extrn error_exit:near 69 extrn fdos_nocrit:near 70 extrn free_all:near 71 extrn get_dseg:near ; Get the PCMODE Data Segment 72 extrn int21_exit:near 73 extrn invalid_function:near 74 extrn dos_entry:near 75 extrn return_AX_CLC:near 76 extrn set_owner:near 77 extrn strlen:near 78 extrn toupper:near 79 extrn valid_drive:near 80 ; 81 ; 82 ;PC-DOS PSP Creation Update and Maintance routines 83 ; 84 ; ***************************** 85 ; *** DOS Function 55 *** 86 ; *** Create New PSP *** 87 ; ***************************** 88 ; 89 ; entry: DX = New PSP Segment 90 ; SI = Top of Available 91 ; 92 ; This function copies the existing PSP and generates a new Process 93 ; environment. The file table is updated and dos_SI is used to determine 94 ; the process' memory size. The PSP is then made the CURRENT_PSP 95 96 Public func55 97 func55: 0 000052FC B98000 mov cx,PSPLEN/2 ; copy whole PSP 0 000052FF E80300 call create_psp 0 00005302 B0F0 mov al,0F0h 0 00005304 C3 ret 102 103 create_psp: 0 00005305 A1[0000] mov ax,[current_psp] ; All based on the Current PSP 0 00005308 E85600 call copy_psp ; Do the Basic Copy 0 0000530B A1[0000] mov ax,[current_psp] ; get the Current PSP address 0 0000530E 26A31600 mov [es:PSP_PARENT],ax ; and save it in child's psp 108 0 00005312 39D0 cmp ax,dx ; Is this the ROOT level DOS process 0 00005314 740D jz create_psp10 ; Yes because Current PSP == New PSP 111 ; therefore skip the EXEC function 112 ; because this is done by P_CREATE 113 0 00005316 C706[0000]4B00 mov word [FD_FUNC],FD_EXEC ; Must Update the Open Counts ETC. 0 0000531C 8916[0200] mov [FD_PSPSEG],dx ; New PSP address 0 00005320 E8[0000] call fdos_nocrit 117 118 create_psp10: 0 00005323 8C06[0000] mov [current_psp],es ; set the New PSP address 0 00005327 C3 ret 121 122 ; 123 ; ***************************** 124 ; *** DOS Function 26 *** 125 ; *** Create New PSP *** 126 ; ***************************** 127 ; 128 ; entry: DX = New PSP Segment 129 ; 130 Public func26 131 func26: 0 00005328 C43E[0000] les di,[int21regs_ptr] ; Get pointer to INT 21 structure of 0 0000532C 268E4514 mov es,[es:reg_CS + di] ; IP/CS/Flags and get the USER CS this 0 00005330 268B360200 mov si,[es:PSP_MEMORY] ; is used as the PSP for this function 0 00005335 8CC0 mov ax,es ; call and NOT current_psp 0 00005337 B98000 mov cx,PSPLEN/2 ; copy whole PSP 0 0000533A 52 push dx 0 0000533B E82300 call copy_psp 0 0000533E 07 pop es 0 0000533F B91400 mov cx,20 ; default XFT table has twenty files 0 00005342 BF1800 mov di,offset PSP_XFT ; and is in the PSP at this offset 0 00005345 26890E3200 mov [es:PSP_XFNMAX],cx ; say we have 20 files max 0 0000534A 26893E3400 mov [es:PSP_XFTOFF],di 0 0000534F 268C063600 mov [es:PSP_XFTSEG],es 0 00005354 1E push ds 0 00005355 8E1E[0000] mov ds,[current_psp] ; we copy 1st 20 entries of current 0 00005359 C5363400 lds si,[PSP_XFTPTR] ; XFT to the child PSP 0 0000535D F3A4 rep movsb ; we do not update file handle use 0 0000535F 1F pop ds ; counts, unlike Int21/55 0 00005360 C3 ret 151 152 copy_psp: 153 ; copy CX words from AX:0 to DX:0, SI = memory top 0 00005361 56 push si ; Save the Memory TOP 0 00005362 1E push ds 0 00005363 8EC2 mov es,dx ; Point ES to the New PSP 0 00005365 8ED8 mov ds,ax ; Get the current PSP for this function 0 00005367 31C0 xor ax,ax 0 00005369 89C7 mov di,ax 0 0000536B 89C6 mov si,ax 0 0000536D F3A5 rep movsw ; Copy into New PSP 162 0 0000536F 8ED8 mov ds,ax ; Copy the current Terminate, Critical 0 00005371 BE8800 mov si,INT22_OFFSET ; Error and Control Break Handlers 0 00005374 BF0A00 mov di,offset PSP_TERM_IP ; into the new PSP 0 00005377 B106 mov cl,6 0 00005379 F3A5 rep movsw ; BREAK,TERM, CRIT ERR SAVED HERE 0 0000537B 1F pop ds 0 0000537C 268F060200 pop word [es:PSP_MEMORY] 170 0 00005381 26C7060000CD20 mov word [es:PSP_INT20],020CDh ; Interrupt 20h Terminate 0 00005388 26C7063800FFFF mov word [es:PSP_RES1],0FFFFh 0 0000538F 26C7063A00FFFF mov word [es:PSP_RES2],0FFFFh 0 00005396 26C7065000CD21 mov word [es:PSP_DOSCALL],021CDh ; INT 21h Function Call 0 0000539D 26C6065200CB mov byte [es:PSP_DOSRETF],0CBh ; RETF 176 0 000053A3 26C60605009A mov byte [es:PSP_LONGCALL],09Ah ; CALLF AnySeg:MemSize 0 000053A9 26A10200 mov ax,[es:PSP_MEMORY] ; Get the Top of Memory 0 000053AD 29D0 sub ax,dx ; Convert it to Memory Size 0 000053AF 3D0010 cmp ax,1000h ; Check for Over 64Kb 0 000053B2 BBF0FE mov bx,0FEF0h ; Assume Over 64Kb 0 000053B5 730A jae sce_10 0 000053B7 89C3 mov bx,ax ; Convert the Paragragh Length 0 000053B9 B104 mov cl,4 ; to a Byte Length 0 000053BB D3E3 shl bx,cl 0 000053BD 81EB1001 sub bx,110h ; Reserve 110h Bytes for .COM Stack 187 sce_10: 0 000053C1 52 push dx 0 000053C2 26891E0600 mov [es:PSP_LONGOFF],bx ; Save the Byte Length 0 000053C7 31D2 xor dx,dx ; Call 5 Entry Segment 0 000053C9 B8C000 mov ax,INT30_OFFSET ; Call 5 Entry Offset 0 000053CC B104 mov cl,4 0 000053CE D3E8 shr ax,cl ; Entry Offset/16 => EO 0 000053D0 D3EB shr bx,cl ; Jump Offset/16 => JO 0 000053D2 01D0 add ax,dx ; EO + ES 0 000053D4 29D8 sub ax,bx ; EO + ES - JO => JS 0 000053D6 26A30800 mov [es:PSP_LONGSEG],ax 0 000053DA 5A pop dx 0 000053DB C3 ret 200 201 ; 202 ; ***************************** 203 ; *** DOS Function 50 *** 204 ; *** Set Current PSP *** 205 ; ***************************** 206 ; 207 Public func50 208 209 ; WARNING - called on USER stack 210 211 func50: 0 000053DC 891E[0000] mov [current_psp],bx 0 000053E0 C3 ret 214 215 ; ***************************** 216 ; *** DOS Function 51/62 *** 217 ; *** Get Current PSP *** 218 ; ***************************** 219 ; 220 Public func51, func62 221 222 ; WARNING - called on USER stack 223 224 func51: 225 func62: 0 000053E1 8B1E[0000] mov bx,[current_psp] 0 000053E5 895E02 mov [reg_BX + bp],bx 0 000053E8 C3 ret 229 230 ;************************************************** 231 ;************************************************** 232 ;*** *** 233 ;*** Process Control Functions *** 234 ;*** *** 235 ;************************************************** 236 ;************************************************** 237 238 ; ***************************** 239 ; *** DOS Function 31 *** 240 ; *** Terminate and Keep *** 241 ; ***************************** 242 ; 243 Public func31 244 func31: 0 000053E9 B80600 mov ax,6 ; make 6 paragraphs our minimum size 0 000053EC 39D0 cmp ax,dx ; Are we at our minimum size ? 0 000053EE 7201 jb func31_05 0 000053F0 92 xchg ax,dx ; no, enforce 6 paragraphs 249 func31_05: 0 000053F1 C606[0000]03 mov byte [exit_type],TERM_RESIDENT ; Exit by Terminate and Stay Resident 0 000053F6 8B1E[0000] mov bx,[current_psp] ; and set the termination PSP to 0 000053FA 891E[0000] mov [term_psp],bx ; be the Current PSP 253 0 000053FE 1E push ds ; Attempt to modify the memory 0 000053FF 8EDB mov ds,bx ; partition size to that given in DX 0 00005401 89D3 mov bx,dx ; Remember DS and ES are swapped for 0 00005403 E89E06 call mem_setblock ; the internal function. 258 0 00005406 8CD8 mov ax,ds ; Now update the PSP_MEMORY field to 0 00005408 01D8 add ax,bx ; reflect the memory available to 0 0000540A A30200 mov [PSP_MEMORY],ax ; to the application now. Required by 0 0000540D 1F pop ds ; MicroPro WordFinder 263 0 0000540E C706[0000]0000 mov word [load_psp],0000 ; Do not free PSP memory 0 00005414 E91802 jmp f31_term ; Common terminate handler 266 267 ; 268 ; ***************************** 269 ; *** DOS Function 4B *** 270 ; *** Load or Execute Prog *** 271 ; ***************************** 272 ; 273 ; An extra sub-function has been defined which is used by the 274 ; ROOT DOS process loader to ensure compatibility between the 275 ; Initial Register conditions for the ROOT DOS process and that 276 ; of any child process. 277 ; 278 ; 4B80h - GO Sub-Function expects all the internal and 279 ; external data areas to have been setup by a 280 ; previous 4B01h function. Never Fails ! 281 ; 282 ; Undocumented feature: 283 ; AX=4B03 returns SETVER version in AX, or zero 284 ; 285 286 Public func4B 287 func4B: 0 00005417 3C80 cmp al,80h ; Is this the special GO sub-function 0 00005419 7503 jnz f4B_01 ; No Process Normally 0 0000541B E96401 jmp start_child ; Go for It every thing else OK 291 292 f4B_01: 0 0000541E 3C05 cmp al,5 0 00005420 740B je f4B05 ; Sub-Func 5:- Exec Hook 0 00005422 3C03 cmp al,3 0 00005424 7447 je f4B_02 ; Sub-Func 3:- Load Overlay 0 00005426 3C01 cmp al,1 0 00005428 7643 jbe f4B_02 ; Sub-Func 1:- Load and No Execute 299 ; Sub-Func 0:- Load and Execute 300 f4B_invalid: 0 0000542A E9[0000] jmp invalid_function ; Otherwise illegal Sub-Function 302 303 f4B05: 304 ;----- 305 ; On Entry: 306 ; ES:DX -> ExecState 307 labelsize esReserved, word, 0 ; reserved, must be zero 308 labelsize esFlags, word, 2 ; type flags 309 labelsize esProgName, dword, 4 ; points to ASCIIZ name 310 labelsize esPSP, word, 8 ; PSP of new program 311 labelsize esStartAddress, dword, 10 ; CS:IP of new program 312 labelsize esProgSize, dword, 14 ; program size, including PSP 313 ; 314 ; type flags 315 ES_EXE equ 0001h 316 ES_OVERLAY equ 0002h 317 ; 318 ; On Exit: 319 ; None (A20 gate disabled) 320 ; 0 0000542D 89D7 mov di,dx ; ES:DI -> ExecState 0 0000542F 26F74502FEFF test word [es:esFlags + di],~ ES_EXE 0 00005435 75F3 jnz f4B_invalid ; only COM or EXE supported 0 00005437 E8[0000] call return_AX_CLC ; assume success 0 0000543A 26C57504 lds si,[es:esProgName + di] ; DS:SI -> ASIIZ name 0 0000543E 268E4508 mov es,[es:esPSP + di] ; ES = PSP 0 00005442 06 push es ; save for DX on exit 0 00005443 E84005 call SetPspNameAndVersion ; set up the name/version fields 0 00005446 5A pop dx ; DX = PSP 0 00005447 16 push ss 0 00005448 1F pop ds ; DS = pcmode data again 0 00005449 FA cli ; Stop anybody interfering 0 0000544A C42E[0000] les bp,[int21regs_ptr] ; point to user stack 0 0000544E 26C746000000 mov word [es:reg_AX + bp],0 ; return successful 0 00005454 26836616FE and word [es:reg_FLAGS + bp],~ CARRY_FLAG 0 00005459 A1[0000] mov ax,[prev_int21regs_off] 0 0000545C A3[0000] mov [int21regs_off],ax 0 0000545F A1[0000] mov ax,[prev_int21regs_seg] 0 00005462 A3[0000] mov [int21regs_seg],ax 0 00005465 FE0E[0000] dec byte [indos_flag] ; no longer in DOS 0 00005469 FF2E[0000] jmp far [func4B05_stub] ; exit via stub code 342 343 344 f4B_02: 0 0000546D 31C0 xor ax,ax 0 0000546F A3[0000] mov [load_env],ax ; Load environment NOT allocated 0 00005472 A3[0000] mov [load_psp],ax ; Load memory NOT allocated 0 00005475 48 dec ax 0 00005476 A3[0000] mov [load_handle],ax ; Mark Load file as CLOSED 350 0 00005479 06 push es 0 0000547A 52 push dx ; expand the filename to a 0 0000547B E88202 call get_filename ; full path to be inherited 0 0000547E 5A pop dx 0 0000547F 07 pop es ; in the environment 356 f4B_10 equ f4b_10 ; NASM port label 0 00005480 7250 jc f4B_10 ; Exit on error 0 00005482 B8203D mov ax,(MS_X_OPEN*256)+20h ; Open File 359 ; mov al,0$010$0$000B ; ReadOnly & DenyWrite 0 00005485 E8[0000] call dos_entry 0 00005488 7312 jnc f4B_05 ; Save Handle if No Error 362 0 0000548A 83F8E0 cmp ax,ED_SHAREFAIL ; Check for a Sharing Error or Access 0 0000548D 7405 jz f4B_04 ; Denied if neither error codes then 0 0000548F 83F8FB cmp ax,ED_ACCESS ; Don't retry the Open function 0 00005492 753E jnz f4B_10 ; in compatibility 367 368 f4B_04: 0 00005494 B8003D mov ax,(MS_X_OPEN*256)+0 ; retry the open in read-only 370 ; mov al,0$000$0$000B ; compatibility mode 0 00005497 E8[0000] call dos_entry 0 0000549A 7236 jc f4B_10 ; Stop On error 373 374 f4B_05: 0 0000549C 1E push ds 0 0000549D 07 pop es ; ES local again 0 0000549E A3[0000] mov [load_handle],ax ; Save for Error Handling 0 000054A1 93 xchg ax,bx ; Get the File Handle 0 000054A2 BE[0000] mov si,offset exe_buffer 0 000054A5 E89105 call get_execdata 0 000054A8 7228 jc f4B_10 0 000054AA E80806 call point_param_block ; CL = subfunc, ES:DI -> param block 0 000054AD 80F903 cmp cl,3 ; Sub-Func 3:- Load Overlay 0 000054B0 7522 jne f4B_go ; Sub-Func 0:- Load and Execute 385 ; Sub-Func 1:- Load and No Execute 386 0 000054B2 268B7502 mov si,[es:2 + di] ; si = Relocation Factor 0 000054B6 268B3D mov di,[es:di] ; di = Load Segment 389 0 000054B9 E87003 call loadimage ; load and relocate image 0 000054BC 7214 jc f4B_10 ; f4B_error - Return with an error 0 000054BE BE[0000] mov si,offset load_file ; Copy the process name into the DMD 0 000054C1 E8DF04 call FindName ; DS:SI -> start of name 0 000054C4 E82605 call GetVersion ; AX = version to return 0 000054C7 8E06[0000] mov es,[current_psp] ; poke the current psp 0 000054CB 26A34000 mov [es:PSP_VERSION],ax ; with the version number 0 000054CF E9[0000] jmp return_AX_CLC ; All done 398 f4b_10: 0 000054D2 EB6F jmp f4B_error 400 401 402 ; 403 ; F4B_GO loads and executes the file whose handle is in BX. 404 ; This routine corresponds to sub-functions 0 and 1. 405 ; 406 f4B_go: 0 000054D4 31C0 xor ax,ax 0 000054D6 BE[0000] mov si,offset exe_buffer ; .COM and .EXE file loading 0 000054D9 A2[0000] mov [exe_loadhigh],al ; Reset the Load High Flag 0 000054DC 3B440C cmp ax,[EXE_MAXPARA + si] 0 000054DF 7507 jnz f4B_g15 ; Load High Flag (MAXPARA == 0) 0 000054E1 48 dec ax 0 000054E2 A2[0000] mov [exe_loadhigh],al ; Set the internal LOADHIGH flag 0 000054E5 89440C mov [EXE_MAXPARA + si],ax ; and allocate all memory 415 f4B_g15: 0 000054E8 268B05 mov ax,[es:di] ; get ENV pointer from param block 0 000054EB E85E02 call build_env ; Build the environment 0 000054EE 7253 jc f4B_error ; Stop on error 419 0 000054F0 E8C602 call calc_psp ; calculate new psp 0 000054F3 724E jc f4B_error ; Stop on error 0 000054F5 E8F603 call pblk_to_psp ; Copy parameters into PSP 0 000054F8 8B36[0000] mov si,[load_image] ; read the Load image 0 000054FC 89F7 mov di,si ; to previously calculated address 0 000054FE E82B03 call loadimage ; load in com file 0 00005501 7240 jc f4B_error ; quit if no memory 0 00005503 E82A04 call set_up_psp ; build child's psp 0 00005506 8B16[0000] mov dx,[load_psp] ; point at PSP seg 429 0 0000550A C606[0000]00 mov byte [exit_type],TERM_NORMAL ; Initialise the Return code type 0 0000550F BE[0000] mov si,offset exe_buffer ; to normal an go 0 00005512 E86405 call check_exe 0 00005515 720C jc f4B_go_com 434 0 00005517 8B16[0000] mov dx,[load_image] ; Get the Load Paragraph 0 0000551B 015416 add [EXE_CS + si],dx ; bias the code segment 0 0000551E 01540E add [EXE_SS + si],dx ; and the stack segment too 0 00005521 EB5F jmp start_child ; goodbye! 439 ; 440 f4B_go_com: ; Go for it .COM 441 ; mov dx,load_psp ; based at PSP seg 0 00005523 895416 mov [EXE_CS + si],dx ; set up initial cs:ip 0 00005526 C744140001 mov word [EXE_IP + si],100h ; and ss:sp for child 0 0000552B 89540E mov [EXE_SS + si],dx 0 0000552E 8EC2 mov es,dx 0 00005530 268B1E0600 mov bx,[es:PSP_LONGOFF] ; ax = segment size in bytes 0 00005535 81C30E01 add bx,110h - 2 ; Initialise stack in reserved area 0 00005539 895C10 mov [EXE_SP + si],bx ; save as stack ptr 0 0000553C 26C7070000 mov word ptr [es:bx],0 ; put one zero on the stack 0 00005541 EB3F jmp start_child ; goodbye! 451 ; 452 ; Function 4B Error Handler. This exit routine will free all 453 ; resources allocated to a process during the EXEC function and 454 ; exit to the standard error handler with the original error code 455 ; if any further errors occur they are ignored. 456 ; 457 f4B_error: 0 00005543 50 push ax ; Save the return Code 0 00005544 8B1E[0000] mov bx,[load_handle] ; Is the load file still open ? 0 00005548 43 inc bx ; (FFFF = closed) 0 00005549 7406 jz f4B_e10 ; YES then Close 0 0000554B 4B dec bx 0 0000554C B43E mov ah,MS_X_CLOSE 0 0000554E E8[0000] call dos_entry 465 f4B_e10: ; Now Free any memory allocated 0 00005551 8B0E[0000] mov cx,[load_psp] ; during the execution of FUNC4B 0 00005555 E85105 call conditional_mem_free ; firstly free PSP/code/data memory 0 00005558 8B0E[0000] mov cx,[load_env] ; Secondly free the memory allocated 0 0000555C E84A05 call conditional_mem_free ; to hold the ENVIRONMENT 0 0000555F 58 pop ax ; Restore the return code and exit 0 00005560 C606[0000]18 mov byte [valid_flg],OK_RF ; fiddle to resume func 4B if we get 0 00005565 8926[0000] mov [retry_sp],sp ; a critical error 0 00005569 C706[0000][1B01] mov word [retry_off],offset func4B 0 0000556F E8[0000] call error_exit ; call the standard error handler 0 00005572 83F80B cmp ax,-ED_FORMAT ; errors less than ED_FORMAT are OK. 0 00005575 720A jb f4B_e20 ; (eg. ED_MEMORY, ED_FILE) 0 00005577 A1[0000] mov ax,[load_handle] ; if we didn't manage to open exec file 0 0000557A 40 inc ax ; load_handle=FFFF and we want to 0 0000557B B003 mov al,-ED_PATH ; return ED_PATH 0 0000557D 7402 jz f4B_e20 ; else we had an error during the load 0 0000557F B00B mov al,-ED_FORMAT ; and should return ED_FORMAT 482 f4B_e20: 0 00005581 C3 ret 484 485 start_child: 0 00005582 8E06[0000] mov es,[current_psp] ; ds -> psp 0 00005586 BA8000 mov dx,0080h ; default dma offset 0 00005589 B41A mov ah,MS_F_DMAOFF ; Set the DMA address 0 0000558B E8[0000] call dos_entry ; set child's dma address 0 0000558E BE[0000] mov si,offset exe_buffer ; Get EXE Buffer Offset 0 00005591 E82105 call point_param_block ; CL = subfunc, ES:DI -> param block 0 00005594 80F901 cmp cl,1 0 00005597 751F jne start_child_go ; load restisters and go 494 ; 495 ; The following code updates the Extended parameter block 496 ; used with the LOAD for DEBUG sub-function. 497 ; 0 00005599 83C70E add di,4*3+2 ; skip user supplied info 0 0000559C 8B4410 mov ax,[EXE_SP + si] 0 0000559F 48 dec ax 0 000055A0 48 dec ax ; return ss:sp-2 0 000055A1 AB stosw 0 000055A2 93 xchg ax,bx ; save SP for later 0 000055A3 8B440E mov ax,[EXE_SS + si] 0 000055A6 AB stosw 506 0 000055A7 1E push ds 0 000055A8 8ED8 mov ds,ax 0 000055AA C7070000 mov word ptr [bx],0 ; zero on user stack 0 000055AE 1F pop ds 511 0 000055AF 8D7414 lea si,[EXE_IP + si] ; point at IP 0 000055B2 AD lodsw 0 000055B3 AB stosw ; copy it, and get in AX for return 0 000055B4 A5 movsw ; copy EXE_CS too 0 000055B5 E9[0000] jmp return_AX_CLC ; all went OK 517 518 start_child_go: 519 ;-------------- 520 ; 521 ; Set the initial registers conditions for a DOS process 522 ; Check the validity of the drives specified in FCB 1 and FCB 2 523 ; of the loading PSP and initialise the AX register accordingly. 524 ; 0 000055B8 31D2 xor dx,dx ; start with valid drives 0 000055BA 8E06[0000] mov es,[current_psp] ; Get the PSP Address and check 0 000055BE 52 push dx 0 000055BF 26A05C00 mov al,[es:PSP_FCB1] ; if the drive specifier for FCB1 0 000055C3 E8[0000] call valid_drive ; is invalid set AL to FF 0 000055C6 5A pop dx 0 000055C7 7402 jz reg_s10 0 000055C9 B2FF mov dl,0FFh 533 reg_s10: 0 000055CB 52 push dx 0 000055CC 26A06C00 mov al,[es:PSP_FCB2] ; if the drive specifier for FCB2 0 000055D0 E8[0000] call valid_drive ; is invalid set AH to FF 0 000055D3 5A pop dx 0 000055D4 7402 jz reg_s20 0 000055D6 B6FF mov dh,0FFh 540 reg_s20: 0 000055D8 8B7C10 mov di,[EXE_SP + si] ; Get the new stack address 0 000055DB 57 push di ; save it 0 000055DC B104 mov cl,4 0 000055DE D3EF shr di,cl ; convert SP to para's 0 000055E0 7503 jnz reg_s30 0 000055E2 BF0010 mov di,1000h ; if 0k make it 64k 547 reg_s30: 0 000055E5 A1[0000] mov ax,[load_max] ; find top of prog area 0 000055E8 2B440E sub ax,[EXE_SS + si] ; find para's left for stack 0 000055EB 39C7 cmp di,ax ; SP too high ? 0 000055ED 5F pop di ; assume OK 0 000055EE 7204 jb reg_s40 0 000055F0 89C7 mov di,ax ; no, so lower SP 0 000055F2 D3E7 shl di,cl ; convert to bytes 555 reg_s40: 0 000055F4 8B4C0E mov cx,[EXE_SS + si] ; CX:DI -> initial stack 0 000055F7 C47414 les si,[EXE_IP + si] ; get initial CS:IP 0 000055FA FA cli 0 000055FB A1[0000] mov ax,[current_psp] ; AX = PSP we are going to use 0 000055FE 92 xchg ax,dx 0 000055FF C606[0000]00 mov byte [indos_flag],0 ; zap the indos flag 562 %if 0 563 mov ss,cx ; switch to new USER stack 564 mov sp,di 565 push es 566 push si ; CS:IP on USER stack 567 mov ds,dx ; DS = ES = PSP we are exec'ing 568 mov es,dx 569 xor bx,bx ; BX = zero, set flags 570 sti 571 retf ; lets go! 572 %else 0 00005604 FF2E[0000] jmp far [exec_stub] 574 %endif 575 576 ; ***************************** 577 ; *** DOS Function 00 *** 578 ; *** Terminate Process *** 579 ; ***************************** 580 ; 581 ; This code is executed for both INT 20 and INT 21/00 and they both 582 ; implicitly set the current PSP to the users calling CODE segment. 583 ; This overwrites the correct value held in CURRENT_PSP. 584 ; 585 Public func00 586 func00: 0 00005608 C606[0000]00 mov byte [int21AX],0 ; force return code of zero 0 0000560D C43E[0000] les di,[int21regs_ptr] 0 00005611 268B5D14 mov bx,[es:reg_CS + di] ; normally users CS is current_psp 0 00005615 A1[0000] mov ax,[current_psp] ; but application call here 0 00005618 39D8 cmp ax,bx ; with an Int 20 at funny moments 0 0000561A 740A je func4c ; (I have "NOW!" in mind) 0 0000561C 8EC3 mov es,bx ; fiddle CS PSP parent so we return to 0 0000561E 26A31600 mov [es:PSP_PARENT],ax ; current_psp then fiddle current_psp 0 00005622 891E[0000] mov [current_psp],bx ; to be user CS 596 597 ; ***************************** 598 ; *** DOS Function 4C *** 599 ; *** Terminate Process *** 600 ; ***************************** 601 ; 602 func4C equ func4c ; NASM port label 603 Public func4C 604 func4c: 0 00005626 A1[0000] mov ax,[current_psp] ; the current PSP is terminating 0 00005629 A3[0000] mov [term_psp],ax ; so set term_psp and load_psp 0 0000562C A3[0000] mov [load_psp],ax ; to that value 608 609 f31_term: ; INT27 and INT21/31 Entry Point 0 0000562F 1E push ds 0 00005630 8E1E[0000] mov ds,[term_psp] 0 00005634 31C0 xor ax,ax 0 00005636 8EC0 mov es,ax ; Copy the Three interrupt vectors 0 00005638 BE0A00 mov si,offset PSP_TERM_IP ; saved on process creation from the 0 0000563B BF8800 mov di,INT22_OFFSET ; termination PSP to the interrupt 0 0000563E B90600 mov cx,6 ; vector table. 0 00005641 F3A5 rep movsw 0 00005643 B80082 mov ax,8200h ; call the REDIR hooks to clean up 0 00005646 CD2A int 2ah ; first the server hook 0 00005648 B82211 mov ax,I2F_PTERM ; then call cleanup code 0 0000564B CD2F int 2fh ; via magic INT 2F call 0 0000564D 1F pop ds ; back to PCMODE data 0 0000564E A0[0000] mov al,byte ptr [int21AX] ; Get the User Return Code 0 00005651 A2[0000] mov [user_retcode],al ; Save the User Ret Code and Set the 0 00005654 B000 mov al,TERM_NORMAL ; Now get the Termination Type 0 00005656 8606[0000] xchg al,[exit_type] ; and exchange with the default value 0 0000565A A2[0000] mov [system_retcode],al ; EXIT_TYPE is set so Non-Zero values 628 ; when a Special Form of termination 629 ; takes place. ie INT 27h 630 631 ; But thence came VTERM, and it looked upon terminating the ROOT process, 632 ; and saw that it was good. 633 ; 634 ; VTERM gives access to the cmdline by doing func31 and becoming a TSR. You can 635 ; then re-invoke it with a hot-key but the next time you invoke the cmdline 636 ; option does a func4C in whatever context it was re-invoked in. This will 637 ; either blow away an application, or try and terminate the ROOT process. 638 639 0 0000565D 8E06[0000] mov es,[term_psp] ; make the terminating PSP's 0 00005661 26A11600 mov ax,[es:PSP_PARENT] ; parental PSP into the 0 00005665 8B1E[0000] mov bx,[current_psp] 0 00005669 39D8 cmp ax,bx ; Is the user trying to terminate 0 0000566B 7450 jz f4C_20 ; the ROOT DOS process if YES then 645 ; skip freeing resources (VTERM) 646 0 0000566D 8B0E[0000] mov cx,[load_psp] ; if we are TSR'ing 0 00005671 E34A jcxz f4C_20 ; skip the free 649 0 00005673 50 push ax ; save parental PSP 0 00005674 8EC3 mov es,bx ; ES = current PSP 0 00005676 31DB xor bx,bx ; start with handle zero 653 f4C_10: 0 00005678 B43E mov ah,MS_X_CLOSE ; close this handle 0 0000567A E8[0000] call dos_entry ; so freeing up PSP entry 0 0000567D 43 inc bx ; onto next handle 0 0000567E 263B1E3200 cmp bx,[es:PSP_XFNMAX] ; done them all yet? 0 00005683 72F3 jb f4C_10 0 00005685 C706[0000]4C00 mov word [FD_FUNC],FD_EXIT ; Must Close all Open FCB's 0 0000568B E8[0000] call fdos_nocrit 0 0000568E 1E push ds ; We have already closed all the 0 0000568F 07 pop es ; open MSNET files we know about 0 00005690 B81D11 mov ax,I2F_PCLOSE ; but we will call the MSNET 0 00005693 CD2F int 2fh ; extention's cleanup code anyway 665 0 00005695 16 push ss 0 00005696 1F pop ds ; reload DS with data segment 668 0 00005697 8B1E[0000] mov bx,[current_psp] ; free all memory associated 0 0000569B E8[0000] call free_all ; with this PSP 671 0 0000569E 16 push ss 0 0000569F 1F pop ds 0 000056A0 BF[0000] mov di, offset lfn_find_handles 675 f4C_close_lfn_handle_loop: 0 000056A3 8B1D mov bx, word ptr [di] 0 000056A5 85DB test bx, bx ; in use ? 0 000056A7 740C jz f4C_close_lfn_handle_next ; no --> 0 000056A9 A1[0000] mov ax, [current_psp] 0 000056AC 3907 cmp word ptr [bx], ax ; we are owner ? 0 000056AE 7505 jne f4C_close_lfn_handle_next ; no --> 0 000056B0 57 push di 0 000056B1 E8[0000] call lfn_free_handle 0 000056B4 5F pop di 685 f4C_close_lfn_handle_next: 0 000056B5 AF scasw ; di += 2 0 000056B6 81FF[0000] cmp di, offset lfn_find_handles_end 0 000056BA 72E7 jb f4C_close_lfn_handle_loop 689 0 000056BC 58 pop ax ; recover parental PSP 691 f4C_20: 0 000056BD A3[0000] mov [current_psp],ax ; make current PSP = parental PSP 693 694 ; 695 ; Function 4C requires a different termination technique. It needs 696 ; to return to the parent process on the stack that was used on the 697 ; function 4B. The interrupt structure has been forced to contain 698 ; the interrupt 22 vector. Therefore all registers will contain 699 ; their original values unless the stack has been overlayed 700 ; 701 ; 0 000056C0 FA cli ; Stop anybody interfering 0 000056C1 C606[0000]00 mov byte [indos_flag],0 ; Force the INDOS_FLAG to 0 for PCTOOLS 0 000056C6 C606[0000]00 mov byte [error_flag],0 ; and SideKick Plus. 0 000056CB A1[0000] mov ax,[retcode] 0 000056CE 8E1E[0000] mov ds,[current_psp] 0 000056D2 8E163000 mov ss,[PSP_USERSS] ; Retrieve the entry SS and SP from 0 000056D6 8B262E00 mov sp,[PSP_USERSP] ; the PSP and return with all 0 000056DA 89E5 mov bp,sp ; registers as on user entry 0 000056DC 894600 mov [reg_AX + bp],ax ; Set AX to the Process RETCODE 0 000056DF 31C0 xor ax,ax 0 000056E1 8ED8 mov ds,ax 0 000056E3 A18800 mov ax,word ptr [INT22_OFFSET] 0 000056E6 894612 mov [reg_IP + bp],ax ; PSP_TERM_IP 0 000056E9 A18A00 mov ax,word ptr [INT22_OFFSET+2] 0 000056EC 894614 mov [reg_CS + bp],ax ; PSP_TERM_CS 0 000056EF C7461602B2 mov word [reg_FLAGS + bp],0b202h ; force flags to 0F202h 718 ; ie Interrupts enabled and 719 ; NEC processor Mode Switch SET 720 ; changed to B202 to have clear 721 ; NT flag (DPMS doesn't like it) 0 000056F4 E9[0000] jmp int21_exit ; Jump to the Exit routine 723 724 725 ; ***************************** 726 ; *** DOS Function 4D *** 727 ; *** Get Sub-Func Ret-Code *** 728 ; ***************************** 729 ; 730 Public func4D 731 func4D: 0 000056F7 31C0 xor ax,ax ; Zero the return code for 0 000056F9 8706[0000] xchg ax,[retcode] ; subsequent calls and return the 0 000056FD E9[0000] jmp return_AX_CLC ; saved value to the caller 735 736 ;**************************************** 737 ;* * 738 ;* Process Control Subroutines * 739 ;* * 740 ;**************************************** 741 742 ; 743 ; We need a full pathname for the application to inherit in it's environment. 744 ; MS_X_EXPAND can't do the job - it returns a PHYSICAL path which may be 745 ; unreachable (bug circa DRDOS 3.41). 746 ; On Entry: 747 ; ES:DX Points to the Original FileName 748 ; On Exit: 749 ; None 750 ; 751 752 get_filename: 0 00005700 1E push ds 0 00005701 06 push es ; swap ES and DS 0 00005702 1F pop ds 0 00005703 07 pop es 0 00005704 89D6 mov si,dx ; DS:SI -> filename 0 00005706 BF[0000] mov di,offset load_file ; ES:DI -> local buffer 0 00005709 B94C00 mov cx,MAX_PATHLEN-4 ; max length (allow for d:\,NUL) 0 0000570C AD lodsw ; get 1st two chars in filename 0 0000570D 80FC3A cmp ah,':' ; is a drive specified ? 0 00005710 7408 je get_filename10 0 00005712 4E dec si 0 00005713 4E dec si ; forget we looked 0 00005714 36A0[0000] mov al,[ss:current_dsk] ; and use the default drive 0 00005718 0441 add al,'A' 767 get_filename10: 0 0000571A AA stosb ; put in the drive 0 0000571B 241F and al,1fh ; convert from ASCII to 1 based 0 0000571D 92 xchg ax,dx ; keep in DL for ms_x_curdir 0 0000571E B83A5C mov ax,':'+256*'\' ; make it "d:\" 0 00005721 AB stosw 0 00005722 AC lodsb ; do we start at the root ? 0 00005723 3C5C cmp al,'\' 0 00005725 741D je get_filename20 0 00005727 3C2F cmp al,'/' 0 00005729 7419 je get_filename20 0 0000572B 4E dec si ; forget we looked for a root 0 0000572C 56 push si ; save where we were 0 0000572D B447 mov ah,MS_X_CURDIR 0 0000572F 89FE mov si,di ; ES:SI -> buffer 0 00005731 E8[0000] call dos_entry ; get current directory 0 00005734 31C0 xor ax,ax 0 00005736 F2AE repne scasb ; look for NUL 0 00005738 96 xchg ax,si ; AX = start of path 0 00005739 5E pop si ; recover pointer to source 0 0000573A 750A jne get_filename30 0 0000573C 4F dec di ; point at NUL 0 0000573D 39F8 cmp ax,di ; are we at the root ? 0 0000573F 7403 je get_filename20 0 00005741 B05C mov al,'\' 0 00005743 AA stosb ; no, append a '\' 793 get_filename20: 0 00005744 F3A4 rep movsb ; copy the remainder of the string 795 get_filename30: 0 00005746 31C0 xor ax,ax 0 00005748 AA stosb ; ensure we are terminated 0 00005749 06 push es 0 0000574A 1F pop ds ; DS back to nornal 0 0000574B C3 ret 801 802 803 ; 804 ; BUILD_ENV determines the size of the Source environment and 805 ; allocates memory and finally copies it. 806 ; 807 ; ON entry AX contains the segment address of the environment 808 ; to be used or zero if the parents is to be copied. 809 build_env: 0 0000574C 8EC0 mov es,ax ; Assume user has specified the 0 0000574E 09C0 or ax,ax ; environment to be used. If AX is 0 00005750 750F jnz b_e10 ; 0000 then use the current environment 0 00005752 8E06[0000] mov es,[current_psp] 0 00005756 268B0E2C00 mov cx,[es:PSP_ENVIRON] ; Current Environment Segment 0 0000575B 8EC1 mov es,cx ; If the current environment segment 0 0000575D 89CF mov di,cx ; is zero then return a size of 0 0000575F E351 jcxz b_e35 ; zero bytes 818 819 b_e10: 0 00005761 31C0 xor ax,ax ; Now determine the Environment size 0 00005763 B90080 mov cx,32*1024 ; CX is maximum size 0 00005766 89C7 mov di,ax 823 b_e20: 0 00005768 F2AE repnz scasb ; Look for two zero bytes which 0 0000576A E348 jcxz b_e40 ; mark the end of the environment 0 0000576C 263A05 cmp al,byte ptr [es:di] ; continue search till the end is found 0 0000576F 75F7 jnz b_e20 0 00005771 4F dec di ; DI == Environment Size - 2 829 830 b_e30: 0 00005772 BE[0000] mov si,offset load_file ; Get the Load pathname length 0 00005775 E8[0000] call strlen ; String length returned in CX 0 00005778 41 inc cx ; Add in the terminator 834 0 00005779 53 push bx 0 0000577A 89CB mov bx,cx ; Get the String Length 0 0000577C 01FB add bx,di ; Add the environment size 0 0000577E 83C313 add bx,15 + 4 ; and convert to paragraphs 0 00005781 D1EB shr bx,1 0 00005783 D1EB shr bx,1 0 00005785 D1EB shr bx,1 0 00005787 D1EB shr bx,1 0 00005789 891E[0000] mov [load_envsize],bx ; Save the Environment Size 0 0000578D E80F03 call mem_alloc ; allocate the memory 0 00005790 5B pop bx 0 00005791 7224 jc b_e50 0 00005793 A3[0000] mov [load_env],ax ; Save the Environment location 0 00005796 51 push cx 0 00005797 57 push di ; Save STRLEN and Offset 0 00005798 1E push ds ; Save DS 0 00005799 06 push es 0 0000579A 8EC0 mov es,ax ; Point ES at the NEW environment 0 0000579C 1F pop ds ; Point DS at the Old environment 0 0000579D 89F9 mov cx,di ; Get the environment size 0 0000579F 31F6 xor si,si 0 000057A1 89F7 mov di,si ; Initialize the pointers 0 000057A3 F3A4 rep movsb ; and copy. Nothing moves if CX == 0 0 000057A5 1F pop ds 859 0 000057A6 5F pop di 0 000057A7 59 pop cx ; Get the string pointers 0 000057A8 31C0 xor ax,ax 0 000057AA AB stosw ; Add terminating zeros 0 000057AB 40 inc ax 0 000057AC AB stosw ; Initialise the String COUNT field 866 867 0 000057AD BE[0000] mov si,offset load_file ; and size information and 0 000057B0 F3A4 rep movsb ; copy the load filename. 870 b_e35: 0 000057B2 F8 clc ; Return with no errors 0 000057B3 C3 ret 873 b_e40: 0 000057B4 B8F6FF mov ax,ED_ENVIRON ; Invalid environment 875 b_e50: 0 000057B7 F9 stc 0 000057B8 C3 ret 878 879 880 ; Calculate the new program segment prefix 881 ; save: bx -> Handle 882 calc_psp: 0 000057B9 53 push bx 0 000057BA BE[0000] mov si,offset exe_buffer ; Calculate the Minimum and Maximum 885 ; amount of memory required to load 0 000057BD E8C702 call image_size ; the program image (Returned in DX) 0 000057C0 83C210 add dx,PSPLEN/16 ; Do not forget the PSP 0 000057C3 89D1 mov cx,dx ; Save the Load Image Size 0 000057C5 89D3 mov bx,dx ; BX will be memory required 0 000057C7 B8F8FF mov ax,ED_MEMORY 0 000057CA 03540A add dx,[EXE_MINPARA + si] ; force DX to be the minimum and if 0 000057CD 725B jc cp_exit ; more than 1 MByte exit with error 0 000057CF 035C0C add bx,[EXE_MAXPARA + si] ; add the maximum amount of memory 0 000057D2 7303 jnc c_p10 ; to the load image size 0 000057D4 BBFFFF mov bx,0FFFFh ; clipping to 1 MByte 896 c_p10: 897 %if HILOAD 0 000057D7 F606[0000]80 test byte [mem_strategy],80h ; HILOAD ON ? 0 000057DC 741B jz c_p15 0 000057DE 89D3 mov bx,dx ; use minimum amount of memory 0 000057E0 83C340 add bx,40h ; add 1 K extra for luck (stack etc) 0 000057E3 E8B902 call mem_alloc ; Allocate the requested block 0 000057E6 7242 jc cp_exit ; if alloc fails exit with error 0 000057E8 1E push ds 0 000057E9 8ED8 mov ds,ax 0 000057EB BBFFFF mov bx,0ffffh ; find how much we can grow this block 0 000057EE E8B302 call mem_setblock 0 000057F1 E8B002 call mem_setblock ; then grow it to that size 0 000057F4 8CD8 mov ax,ds ; ax = base of the block again 0 000057F6 1F pop ds 0 000057F7 EB0E jmp c_p20 912 c_p15: 913 %endif 0 000057F9 E8A302 call mem_alloc ; allocate size and if error occurs 0 000057FC 7309 jnc c_p20 ; then the maximum size is greater 0 000057FE 39D3 cmp bx,dx ; than the minimum required 0 00005800 7228 jc cp_exit ; if not exit with error 918 0 00005802 E89A02 call mem_alloc ; Allocate what we've got 0 00005805 7223 jc cp_exit ; Exit on error 921 c_p20: 0 00005807 A3[0000] mov [load_psp],ax ; Save the load paragraph == PSP 0 0000580A 01C3 add bx,ax ; Save the block top 0 0000580C 891E[0000] mov [load_top],bx 0 00005810 891E[0000] mov [load_max],bx ; save top of block for SP adjust 0 00005814 83C010 add ax,PSPLEN/16 ; Set AX to be the Relocation Paragraph 927 0 00005817 803E[0000]00 cmp byte [exe_loadhigh],0 ; Should the Load Image be 0 0000581C 7409 jz c_p30 ; forced into to High Memory with the 0 0000581E 89D8 mov ax,bx ; data area and PSP loaded low. 0 00005820 29C8 sub ax,cx ; Subtract the Load Image Size from 0 00005822 B91000 mov cx,PSPLEN/16 ; the top of allocated memory and 0 00005825 01C8 add ax,cx ; load at that address. 934 935 c_p30: 0 00005827 A3[0000] mov [load_image],ax ; Save the Address of the Load Image 937 cp_exit: 0 0000582A 5B pop bx 0 0000582B C3 ret 940 941 ;LOADIMAGE: 942 ; 943 ; This function reads in the load image of the file into memory 944 ; (Paragraph DI) asserting the relocation factor (SI) if any relocation 945 ; items exist in the file. The size of the load image is calculated 946 ; using the EXE_SIZE and EXE_FINAL fields enough memory exists at DI 947 ; to load the image. The valid .EXE header has been moved to exe_buffer. 948 ; 949 ; Read in and relocate the EXE image 950 ; entry: bx -> handle 951 ; di = load segment 952 ; si = reloc segment 953 ; exit: cf = 1, ax = Error Code if load fails 954 ; 955 loadimage: 956 ;--------- 0 0000582C E86D00 call readfile ; Read the load image into memory 0 0000582F 7227 jc load_error ; Exit if error 959 0 00005831 8B0E[0600] mov cx,[exe_buffer+EXE_RELCNT] 961 ; get number of reloc entries 0 00005835 E316 jcxz load_done ; if none there, forget it .COM's 963 ; drop out here because RELCNT is zero 964 0 00005837 51 push cx ; seek to 1st relocation entry 0 00005838 31C9 xor cx,cx ; in the file 0 0000583A 8B16[1800] mov dx,[exe_buffer+EXE_RELOFF] 0 0000583E B80042 mov ax,(MS_X_LSEEK*256)+0 0 00005841 E8[0000] call dos_entry 0 00005844 59 pop cx 0 00005845 7211 jc load_error ; stop on error 0 00005847 91 xchg ax,cx ; AX = # items to relocate 0 00005848 E81400 call reloc_image ; relocate the image 0 0000584B 720B jc load_error 975 load_done: 0 0000584D C706[0000]FFFF mov word [load_handle],-1 0 00005853 B43E mov ah,MS_X_CLOSE ; and close the loadfile 0 00005855 E9[0000] jmp dos_entry ; close the com file 979 980 load_error: ; Error exit from relocation 0 00005858 50 push ax ; save error code 0 00005859 E8F1FF call load_done ; close the file 0 0000585C 58 pop ax ; recover error code 0 0000585D F9 stc ; say we had an error 0 0000585E C3 ret 986 987 ; 988 ; The following code will relocate CX items from the open handle BX 989 ; 990 reloc_image: 991 ; On Entry: 992 ; BX = handle 993 ; AX = # items to relocate 994 ; SI = relocation segment 995 ; DI = relocation fixup 996 ; 997 ; On Exit: 998 ; CY clear if OK, else AX = error code 999 1000 0 0000585F 1E push ds 0 00005860 07 pop es ; ES -> Local Buffer Segment 0 00005861 BA[0000] mov dx,offset reloc_buf ; DX -> Local Buffer Offset 1004 0 00005864 B9[0000] mov cx,RELOC_CNT ; AX -> Buffer Size 0 00005867 D1E1 shl cx,1 ; convert reloc size from paras 0 00005869 D1E1 shl cx,1 ; to an item count 0 0000586B 29C8 sub ax,cx ; buffer. which contains a maximum 0 0000586D 7304 jnc reloc_i10 ; of RELOC_SIZE items. 0 0000586F 01C1 add cx,ax ; CX contains # of items to Read 0 00005871 31C0 xor ax,ax ; AX contains # left to read 1012 reloc_i10: 0 00005873 50 push ax ; save # items left to read 0 00005874 51 push cx ; and # reloc to read 0 00005875 D1E1 shl cx,1 0 00005877 D1E1 shl cx,1 ; calculate # byte to read 0 00005879 B43F mov ah,MS_X_READ ; relocation buffer. 0 0000587B E8[0000] call dos_entry 0 0000587E 59 pop cx 0 0000587F 7302 jnc reloc_i20 ; Exit on Error 0 00005881 59 pop cx ; clean up stack 0 00005882 C3 ret ; return with error 1023 1024 reloc_i20: 0 00005883 53 push bx ; save handle 0 00005884 97 xchg ax,di ; AX = reloc fixup 1027 0 00005885 89D3 mov bx,dx ; Get buffer offset 1029 reloc_i30: 0 00005887 014702 add word ptr [2 + bx],ax ; Correct segment to Load Seg 0 0000588A C43F les di,[bx] ; es:di = reloc entry 0 0000588C 260135 add [es:di],si ; add reloc seg into image 0 0000588F 83C304 add bx,4 ; and update for next entry 0 00005892 E2F3 loop reloc_i30 1035 0 00005894 97 xchg ax,di ; restore fixup to DI 0 00005895 5B pop bx ; recover handle 0 00005896 58 pop ax ; recover # left to do 0 00005897 85C0 test ax,ax 0 00005899 75C4 jnz reloc_image ; keep going until all done 0 0000589B C3 ret 1042 1043 ;READFILE 1044 ; 1045 ; This function reads in the load image of the file into memory 1046 ; (Paragraph DI) the size of the load image is calculated using 1047 ; the EXE_SIZE and EXE_FINAL fields enough memory exists at DI 1048 ; to load the image. The valid .EXE header has been moved to 1049 ; exe_buffer. 1050 ; 1051 ; Read in a Binary Image .COM or .EXE 1052 ; entry: bx -> handle 1053 ; di = load segment 1054 ; 1055 ; exit: bx, si, di Preserved 1056 ; cf = 1, ax = Error Code if load fails 1057 ; 1058 MAX_READPARA equ 3200 ; Maximum Number of Paragraphs to 1059 ; read in one command 50Kb 1060 readfile: 0 0000589C 56 push si 0 0000589D 57 push di 0 0000589E BE[0000] mov si,offset exe_buffer ; Get the .EXE header 0 000058A1 8B5408 mov dx,[EXE_HEADER + si] ; get the header size in paragraphs 0 000058A4 B90400 mov cx,4 ; and seek to that offset in the 0 000058A7 D3C2 rol dx,cl ; file before reading any data 0 000058A9 88D1 mov cl,dl 0 000058AB 83E10F and cx,0Fh 0 000058AE 83E2F0 and dx,~ 0Fh 0 000058B1 B80042 mov ax,(MS_X_LSEEK*256)+0 0 000058B4 E8[0000] call dos_entry ; Execute LSEEK Function 0 000058B7 7232 jc rf_error 0 000058B9 E8CB01 call image_size ; Get the Load Image Sizes in Paras 0 000058BC 89D6 mov si,dx ; Returned in DX save in SI 1075 rf_10: 0 000058BE 8EC7 mov es,di ; Set the Buffer address 0 000058C0 29D2 sub dx,dx ; es:dx -> load segment 1078 0 000058C2 81FE800C cmp si,MAX_READPARA ; Can we read the rest of the file 0 000058C6 7614 jbe rf_20 ; in one command jif YES 0 000058C8 81EE800C sub si,MAX_READPARA ; Decrement the Image Size 0 000058CC B900C8 mov cx,MAX_READPARA * 16 ; Number of bytes to read 0 000058CF 81C7800C add di,MAX_READPARA ; Number of Paragraphs Read 0 000058D3 B43F mov ah,MS_X_READ ; Read the Block into the 0 000058D5 E8[0000] call dos_entry ; buffer Exit if Error 0 000058D8 7211 jc rf_error 0 000058DA EBE2 jmp rf_10 ; Else go for the next bit 1088 1089 rf_20: ; Now reading the last part of 0 000058DC B104 mov cl,4 ; the image so convert remainder 0 000058DE D3E6 shl si,cl ; in SI to bytes and Read File 0 000058E0 89F1 mov cx,si 0 000058E2 B43F mov ah,MS_X_READ ; Read data into the buffer 0 000058E4 E8[0000] call dos_entry 0 000058E7 7202 jc rf_error ; Stop on Error 0 000058E9 31C0 xor ax,ax ; Reset the carry Flag and Zero AX 1097 rf_error: ; Error exit Carry Flag Set and AX 0 000058EB 5F pop di 0 000058EC 5E pop si ; contains the error code. 0 000058ED C3 ret 1101 1102 ; Copy old PSP contents to new PSP. 1103 ; Parameter block supplied by user contains command line 1104 ; and default FCB's - copy these into the load_psp. 1105 ; save: bx -> Handle 1106 pblk_to_psp: 0 000058EE 1E push ds ; Save the PcMode Data Segment 0 000058EF 53 push bx ; and file handle 0 000058F0 8B16[0000] mov dx,[load_psp] 0 000058F4 E8BE01 call point_param_block ; ES:DI -> users parameter block 1111 0 000058F7 06 push es 0 000058F8 57 push di 0 000058F9 26C57502 lds si,[es:2 + di] ; Get the Source Pointer 0 000058FD B98000 mov cx,128 ; Copy the complete command line 0 00005900 BF8000 mov di,offset PSP_COMLEN ; because BASCOM places a segment value 0 00005903 8EC2 mov es,dx ; after the CR which was not previously 0 00005905 F3A4 rep movsb ; copied. 0 00005907 5F pop di 0 00005908 07 pop es 1121 0 00005909 26C57506 lds si,[es:6 + di] ; get 1st FCB address 0 0000590D B85C00 mov ax,offset PSP_FCB1 ; First FCB Offset 0 00005910 E80D00 call copy_fcb ; copy FCB 0 00005913 26C5750A lds si,[es:10 + di] ; Get the Source Pointer 0 00005917 B86C00 mov ax,offset PSP_FCB2 ; Second FCB Offset 0 0000591A E80300 call copy_fcb ; copy FCB 0 0000591D 5B pop bx ; file handle back again 0 0000591E 1F pop ds ; Restore PcMode Data Segment 0 0000591F C3 ret 1131 1132 copy_fcb: 1133 ;-------- 1134 ; On Entry: 1135 ; DS:SI -> source 1136 ; DX:AX -> destination 1137 ; On Exit: 1138 ; None 1139 ; ES:DI, DX preserved 1140 ; 0 00005920 06 push es 0 00005921 57 push di 0 00005922 8EC2 mov es,dx 0 00005924 97 xchg ax,di ; ES:DI -> destination 0 00005925 B90C00 mov cx,12 ; Copy Drive, Name and Extension 0 00005928 F3A4 rep movsb ; and copy it 0 0000592A 91 xchg ax,cx ; AX = 0 0 0000592B AB stosw 0 0000592C AB stosw ; zero last 4 bytes 0 0000592D 5F pop di 0 0000592E 07 pop es 0 0000592F C3 ret 1153 1154 1155 1156 ; Set up a new psp for the child 1157 ; 1158 set_up_psp: 0 00005930 A1[0000] mov ax,[load_psp] ; Change the ownership of the 0 00005933 8B1E[0000] mov bx,[load_env] ; Environment and Load Memory 0 00005937 E8[0000] call set_owner ; partitions. 0 0000593A A1[0000] mov ax,[load_psp] 0 0000593D 89C3 mov bx,ax 0 0000593F E8[0000] call set_owner 1165 0 00005942 833E[0000]01 cmp word [current_psp],1 ; Is This the ROOT DOS process 0 00005947 7513 jnz setup_psp10 ; No! Continue as Normal 1168 0 00005949 A1[0000] mov ax,[load_psp] ; Force the LOAD_PSP to 0 0000594C A3[0000] mov [current_psp],ax ; to be the current PSP 1171 0 0000594F 8EC0 mov es,ax ; Now Zero Fill the New PSP 0 00005951 B92E00 mov cx,(offset PSP_FCB1)/2 ; up to user supplied parameters 0 00005954 31C0 xor ax,ax 0 00005956 89C7 mov di,ax 0 00005958 F3AB rep stosw 0 0000595A EB12 jmp setup_psp20 ; and skip the INT22 Fudge 1178 1179 setup_psp10: ; Get the Function return address 0 0000595C 31FF xor di,di 0 0000595E 8EC7 mov es,di ; and force into INT 22 0 00005960 BF8800 mov di,INT22_OFFSET ; Set Interrupt Vectors 22 0 00005963 1E push ds 0 00005964 C536[0000] lds si,[int21regs_ptr] 0 00005968 8D7412 lea si,[reg_IP + si] ; DS:SI -> callers IP 0 0000596B A5 movsw ; Save User IP 0 0000596C A5 movsw ; Save User CS 0 0000596D 1F pop ds 1189 setup_psp20: 0 0000596E 8B16[0000] mov dx,[load_psp] ; Get the new PSP address 0 00005972 8B36[0000] mov si,[load_top] ; Get the last paragraph allocated 0 00005976 B92E00 mov cx,(offset PSP_FCB1)/2 ; Copy PSP up to user supplied bits 1193 ; 1194 ; CREATE_PSP is a local function called by the DOS EXEC function (4B) 1195 ; to create a new PSP and initialize it as a new process. 1196 ; 1197 ; The PSP_MEMORY field was original calculated as the highest memory 1198 ; location that could be allocated to a process. However this caused 1199 ; Carbon Copy Plus to Fail so the routine now uses the LOAD_TOP 1200 ; value calculated by the CALC_PSP function. This is the last 1201 ; paragraph allocated to the current PSP. 1202 ; 0 00005979 E889F9 call create_psp ; Create the New Process 0 0000597C A1[0000] mov ax,[load_env] ; Now Update the Environment 0 0000597F 26A32C00 mov [es:PSP_ENVIRON],ax 0 00005983 BE[0000] mov si,offset load_file ; Copy the process name into the DMD 1207 ; jmp SetPspNameAndVersion 1208 1209 SetPspNameAndVersion: 1210 ;--------------------- 1211 ; On Entry: 1212 ; ES = PSP 1213 ; DS:SI -> pathaname (nb. DS need not be dos data seg!) 1214 ; On Exit: 1215 ; None 1216 ; 0 00005986 8CC3 mov bx,es 0 00005988 4B dec bx 0 00005989 8EC3 mov es,bx ; ES points at DMD (We Hope) 0 0000598B E8[0000] call check_dmd_id ; Check for a valid DMD 0 0000598E 7212 jc SetPspNameAndVersion10 ; bail out now if none 0 00005990 43 inc bx ; BX -> PSP again 0 00005991 53 push bx ; keep it on the stack 0 00005992 E80E00 call FindName ; DS:SI -> start of name 0 00005995 56 push si 0 00005996 E82900 call SetName ; update the name field 0 00005999 5E pop si 0 0000599A E85000 call GetVersion ; AX = version to return 0 0000599D 07 pop es ; ES = PSP 0 0000599E 26A34000 mov [es:PSP_VERSION],ax ; set version number 1231 SetPspNameAndVersion10: 0 000059A2 C3 ret 1233 1234 FindName: 1235 ;-------- 1236 ; On Entry: 1237 ; DS:SI -> pathname of file 1238 ; On Exit: 1239 ; DS:SI -> final leaf name of file 1240 ; CX = length of leaf name 1241 ; 0 000059A3 89F1 mov cx,si ; remember start of leaf 1243 FindName10: 0 000059A5 AC lodsb 0 000059A6 3C20 cmp al,' ' ; end of the name ? 0 000059A8 7612 jbe FindName30 0 000059AA E8[0000] call dbcs_lead ; is it a double byte pair ? 0 000059AD 7503 jne FindName20 0 000059AF AC lodsb ; include the second byte 0 000059B0 EBF3 jmp FindName10 1251 FindName20: 0 000059B2 3C5C cmp al,'\' ; is it a seperator ? 0 000059B4 74ED je FindName 0 000059B6 3C2F cmp al,'/' 0 000059B8 74E9 je FindName 0 000059BA EBE9 jmp FindName10 1257 FindName30: 0 000059BC 87CE xchg cx,si ; SI -> start of leaf name 0 000059BE 29F1 sub cx,si 0 000059C0 49 dec cx ; CX = length 0 000059C1 C3 ret 1262 1263 1264 SetName: 1265 ;------- 1266 ; On Entry: 1267 ; DS:SI -> leaf name to update 1268 ; ES = DMD to update 1269 ; On Exit: 1270 ; CX preserved 1271 ; 0 000059C2 BF0800 mov di,offset DMD_NAME ; point at the owners name field 1273 SetName10: 0 000059C5 AC lodsb 0 000059C6 3C20 cmp al,' ' ; end of the name ? 0 000059C8 7619 jbe SetName30 0 000059CA E8[0000] call dbcs_lead ; is it a double byte pair ? 0 000059CD 7509 jne SetName20 0 000059CF AA stosb ; copy 1st byte of pair 0 000059D0 83FF10 cmp di,(offset DMD_NAME)+DMD_NAME_LEN 0 000059D3 730E jae SetName30 ; don't overflow if name too long 0 000059D5 A4 movsb ; and the second 0 000059D6 EBED jmp SetName10 1284 1285 SetName20: 0 000059D8 AA stosb 0 000059D9 3C2E cmp al,'.' ; discard all following '.' 0 000059DB 7406 je SetName30 0 000059DD 83FF10 cmp di,(offset DMD_NAME)+DMD_NAME_LEN 0 000059E0 72E3 jb SetName10 ; don't overflow if name too long 0 000059E2 C3 ret 1292 1293 SetName30: 0 000059E3 4F dec di 0 000059E4 31C0 xor ax,ax 1296 SetName40: 0 000059E6 AA stosb ; zero the '.' 0 000059E7 83FF10 cmp di,(offset DMD_NAME)+DMD_NAME_LEN 0 000059EA 72FA jb SetName40 ; zero the rest of the name 0 000059EC C3 ret 1301 1302 GetVersion: 1303 ;---------- 1304 ; On Entry: 1305 ; DS:SI -> start of name 1306 ; CX = length 1307 ; On Exit: 1308 ; AX = dos version to return 1309 ; 0 000059ED 36C43E[0000] les di,[ss:setverPtr] 0 000059F2 8CC0 mov ax,es 0 000059F4 09F8 or ax,di ; check for a setver list 0 000059F6 750E jnz GetVersion30 1314 GetVersion10: 0 000059F8 36A1[0000] mov ax,[ss:dos_version] ; better use default version 0 000059FC C3 ret 1317 1318 GetVersion20: 0 000059FD 268A45FF mov al,[es:di-1] ; skip the name 0 00005A01 98 cbw 0 00005A02 40 inc ax 0 00005A03 40 inc ax ; skip the version 0 00005A04 01C7 add di,ax ; try the next entry 1324 GetVersion30: 0 00005A06 268A05 mov al,byte ptr [es:di] ; get length field 0 00005A09 84C0 test al,al ; end of the list ? 0 00005A0B 74EB jz GetVersion10 1328 0 00005A0D 47 inc di ; point at potential name 0 00005A0E 38C8 cmp al,cl ; do the lengths match ? 0 00005A10 75EB jne GetVersion20 0 00005A12 31DB xor bx,bx ; start scan with 1st character 1333 GetVersion40: 0 00005A14 8B00 mov ax,[bx+si] ; get a character from filename 0 00005A16 E8[0000] call dbcs_lead ; is it a DBCS character ? 0 00005A19 7506 jne GetVersion50 0 00005A1B 43 inc bx ; we will skip 2 characters 0 00005A1C 263B01 cmp ax,[es:bx+di] ; do both character match ? 0 00005A1F EB0D jmp GetVersion60 1340 1341 GetVersion50: 0 00005A21 E8[0000] call toupper ; upper case it 0 00005A24 88C4 mov ah,al ; save it 0 00005A26 268A01 mov al,[es:bx+di] ; get a character from setver list 0 00005A29 E8[0000] call toupper ; upper case it 0 00005A2C 38E0 cmp al,ah ; do we match ? 1347 GetVersion60: 0 00005A2E 75CD jne GetVersion20 ; no, try next name in list 0 00005A30 43 inc bx ; we match, have we done them all ? 0 00005A31 39CB cmp bx,cx ; check against length 0 00005A33 72DF jb GetVersion40 0 00005A35 268B01 mov ax,[es:bx+di] ; get version number from setver list 0 00005A38 C3 ret 1354 1355 ; 1356 ; GET_DATA reads the EXE header using the handle passed in BX 1357 ; 1358 1359 get_execdata: 1360 ; On Entry: 1361 ; BX = handle 1362 ; ES:SI = buffer 1363 ; On Exit: 1364 ; CY set if error, AX = error code 1365 ; BX/SI preserved 1366 0 00005A39 B43F mov ah,MS_X_READ 0 00005A3B B91C00 mov cx,EXE_LENGTH ; read the exe header 0 00005A3E 89F2 mov dx,si ; ES:DX -> buffer 0 00005A40 E8[0000] call dos_entry ; try and read the data 0 00005A43 7233 jc gd_exit ; Error Exit 0 00005A45 C744020002 mov word [EXE_FINAL + si],0200h ; Force value to Full Page 0 00005A4A E82C00 call check_exe ; all done if it's an .EXE 0 00005A4D 7329 jnc gd_exit 0 00005A4F B80242 mov ax,(MS_X_LSEEK*256)+2 ; it's a .COM 0 00005A52 31C9 xor cx,cx ; seek to end of file 0 00005A54 31D2 xor dx,dx 0 00005A56 E8[0000] call dos_entry ; get file length in DX:AX 0 00005A59 721D jc gd_exit 0 00005A5B 86C4 xchg al,ah 0 00005A5D 88D4 mov ah,dl ; DX:AX / 512 0 00005A5F D1EA shr dx,1 0 00005A61 D1D8 rcr ax,1 0 00005A63 40 inc ax ; Handle Final Partial Page 0 00005A64 894404 mov [EXE_SIZE + si],ax ; No. of 512 Byte Pages 0 00005A67 31C0 xor ax,ax 0 00005A69 894408 mov [EXE_HEADER + si],ax ; Load Image starts a 0000 0 00005A6C 894406 mov [EXE_RELCNT + si],ax ; No Relocation Items 0 00005A6F 48 dec ax ; Force Maximum Memory Allocation 0 00005A70 89440C mov [EXE_MAXPARA + si],ax ; to the .COM 0 00005A73 C7440A1000 mov word [EXE_MINPARA + si],0010h ; give it at least an extra 100h 1392 ; bytes for the Default Stack 1393 gd_exit: 0 00005A78 C3 ret 1395 1396 ; 1397 ; Determine if the file to be loaded is a DOS EXE format file 1398 ; if YES then return with the carry flag reset. Assume that the 1399 ; header has already been read into EXE_HEADER 1400 ; 1401 public check_exe 1402 check_exe: 0 00005A79 813C4D5A cmp word [EXE_SIGNATURE + si],'MZ' ; look for exe signature ; NASM port swapped text literals 0 00005A7D 7407 jz check_e10 0 00005A7F 813C5A4D cmp word [EXE_SIGNATURE + si],'ZM' ; look for exe signature ; NASM port swapped text literals 0 00005A83 7401 jz check_e10 0 00005A85 F9 stc ; flag the error 1408 check_e10: 0 00005A86 C3 ret 1410 1411 ; 1412 ; IMAGE_SIZE assumes SI points to a valid EXE header and from this 1413 ; it calculates the size of the load image and returns this value 1414 ; in paragraphs in DX. AX and CX are corrupted. 1415 ; 1416 Public image_size 1417 image_size: 0 00005A87 8B5404 mov dx,[EXE_SIZE + si] ; No of 512 pages in System Image 0 00005A8A 4A dec dx ; Adjust for Final Partial Page 0 00005A8B B105 mov cl,5 0 00005A8D D3E2 shl dx,cl ; No. 512 Byte Blocks to Para 0 00005A8F 2B5408 sub dx,[EXE_HEADER + si] ; Remove the Header Size 1423 0 00005A92 8B4402 mov ax,[EXE_FINAL + si] 0 00005A95 83C00F add ax,15 0 00005A98 FEC9 dec cl 0 00005A9A D3E8 shr ax,cl ; AX is Partial Block in PARA 0 00005A9C 01C2 add dx,ax ; DX is Image Size in PARA's 0 00005A9E C3 ret 1430 1431 mem_alloc: 0 00005A9F B448 mov ah,MS_M_ALLOC ; call DOS to allocate 0 00005AA1 E9[0000] jmp dos_entry ; some memory 1434 1435 mem_setblock: 0 00005AA4 B44A mov ah,MS_M_SETBLOCK ; call DOS to ajust 0 00005AA6 E9[0000] jmp dos_entry ; a memory block 1438 1439 conditional_mem_free: 1440 ; On Entry: 1441 ; CX = para to free 1442 ; (0 = none to free) 1443 ; On Exit: 1444 ; None 1445 ; 0 00005AA9 E309 jcxz cmem_free10 ; only free up allocated 0 00005AAB 1E push ds ; memory 0 00005AAC 8ED9 mov ds,cx 0 00005AAE B449 mov ah,MS_M_FREE ; free up a memory block 0 00005AB0 E8[0000] call dos_entry 0 00005AB3 1F pop ds 1452 cmem_free10: 0 00005AB4 C3 ret 1454 1455 point_param_block: 1456 ;----------------- 1457 ; On Entry: 1458 ; None 1459 ; On Exit: 1460 ; CL = subfunction number (callers AL) 1461 ; ES:DI -> parameter block (callers ES:BX) 1462 ; AX corrupted 1463 ; 0 00005AB5 C43E[0000] les di,[int21regs_ptr] ; point at callers registers 0 00005AB9 268A0D mov cl,[es:reg_AL + di] ; CL = subfunction# (range-checked) 0 00005ABC 268B4502 mov ax,[es:reg_BX + di] 0 00005AC0 268E4510 mov es,[es:reg_ES + di] ; callers ES:BX -> parameter block 0 00005AC4 97 xchg ax,di ; ES:DI -> parameter block 0 00005AC5 C3 ret 1470 1471 PCM_CODE ends 1472 1473 === Switch to base=00C180h -> "PCMODE_DATA" 1474 section PCMODE_DATA public align=2 class=DATA 1475 extrn current_dsk:byte 1476 extrn current_psp:word 1477 extrn retcode:word ; Complete return code passed to F4B 1478 extrn user_retcode:byte ; User retcode set by funcs 4C and 31 1479 extrn system_retcode:byte ; System retcode returns the cause of 1480 extrn switch_char:byte 1481 extrn mem_strategy:byte ; memory allocation strategy 1482 extrn int21AX:word ; Int 21's AX 1483 extrn indos_flag:byte 1484 extrn int21regs_ptr:dword 1485 extrn int21regs_off:word 1486 extrn int21regs_seg:word 1487 extrn prev_int21regs_off:word 1488 extrn prev_int21regs_seg:word 1489 extrn error_flag:byte 1490 extrn exe_buffer:word 1491 extrn valid_flg:byte 1492 extrn retry_off:word 1493 extrn retry_sp:word 1494 extrn last_drv:byte 1495 extrn exec_stub:dword 1496 extrn func4B05_stub:dword 1497 1498 extrn dos_version:word 1499 extrn setverPtr:dword 1500 1501 ; To improve Network performance the EXE relocation items are 1502 ; now read into the following buffer. All the data items contained 1503 ; between RELOC_BUF and RELOC_SIZE are destroyed by the LOADIMAGE 1504 ; sub-routine when it relocates a DOS .EXE file. 1505 ; 1506 ; Only variables which are unused after the LOADIMAGE function can 1507 ; be placed in this buffer. 1508 ; 1509 ; ******** Start of .EXE Relocation Buffer ******** 1510 ; 1511 1512 ; We can re-use the MSNET pathname buffers during an EXEC 1513 1514 extrn reloc_buf:byte 1515 extrn load_file:byte 1516 extrn RELOC_CNT:abs 1517 1518 ; 1519 ; ******** End of .EXE Relocation Buffer ******** 1520 ; 1521 1522 extrn exit_type:byte 1523 extrn term_psp:word 1524 extrn load_handle:word 1525 extrn load_env:word ; Paragraph of the new environment 1526 extrn load_envsize:word ; Size of new environment 1527 extrn load_psp:word ; Paragraph of the new PSP. 1528 extrn load_image:word ; Paragraph of the Load Image. 1529 extrn load_top:word ; Last paragraph of Allocated Memory 1530 extrn load_max:word ; ditto, but not messed with 1531 extrn exe_loadhigh:byte ; load high flag 1532 1533 PCMODE_DATA ends 1534 === Switch to base=00C180h -> "BDOS_DATA" 1535 section BDOS_DATA public align=2 class=DATA 1536 1537 extrn lfn_find_handles:word 1538 extrn lfn_find_handles_end:word 1539 extrn lfn_find_handle_heap:word 1540 extrn lfn_find_handle_heap_end:word 1541 extrn lfn_find_handle_heap_free:word 1542 1543 BDOS_DATA ends 1544 === Switch to base=000000h -> "PCM_CODE" 1545 section PCM_CODE public align=1 class=CODE 1545 ****************** warning: segment attributes specified on redeclaration of segment: ignoring [-w+other] 1546 1547 extrn lfn_free_handle:near 1548 1549 PCM_CODE ends 1550 1551 end === Trace listing source: drdos/bin/network.lst 1 ; File : $NETWORK.ASM$ 2 ; 3 ; Description : 4 ; 5 ; Original Author : DIGITAL RESEARCH 6 ; 7 ; Last Edited By : $CALDERA$ 8 ; 9 ;-----------------------------------------------------------------------; 10 ; Copyright Work of Caldera, Inc. All Rights Reserved. 11 ; 12 ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, 13 ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. 14 ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES 15 ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF 16 ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO 17 ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE 18 ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE 19 ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, 20 ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, 21 ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, 22 ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF 23 ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT 24 ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND 25 ; CIVIL LIABILITY. 26 ;-----------------------------------------------------------------------; 27 ; 28 ; *** Current Edit History *** 29 ; *** End of Current Edit History *** 30 ; 31 ; $Log$ 32 ; ENDLOG 33 ; 34 ; DOS Network Function Calls 35 36 group PCMCODE PCM_CODE 37 group PCMDATA PCMODE_DATA FDOS_DSEG 38 39 ASSUME DS:PCMDATA 40 41 [list -] 47 === Switch to base=000000h -> "PCM_CODE" 48 section PCM_CODE public align=1 class=CODE 49 50 extrn reload_ES:near 51 extrn return_AX_CLC:near 52 extrn return_CX:near 53 extrn error_exit:near 54 extrn get_ldt_raw:near 55 56 ; ***************************** 57 ; *** DOS Function 5E *** 58 ; *** Get Machine Name *** 59 ; ***************************** 60 ; 61 Public func5E 62 func5E: 0 00005AC6 3C01 cmp al,1 0 00005AC8 7207 jb f5E00 ; Get Machine Name Sub-Function 0 00005ACA 741B je f5E01 ; Set Machine Name Sub-Function 0 00005ACC B81F11 mov ax,I2F_REDIR_5E ; magic int 2F number 0 00005ACF EB61 jmp func5F_common ; use common routine 68 ; 69 ; Get the current Machine Name 70 ; 71 f5E00: 0 00005AD1 89D7 mov di,dx ; Copy the 15 Byte Network Name 0 00005AD3 BE[0000] mov si,offset net_name 0 00005AD6 B90800 mov cx,16/2 0 00005AD9 F3A5 rep movsw 76 ; mov ch,name_num ; 00 -> Undefined Name 77 ; mov cl,netbios ; 00 -> Name Number 0 00005ADB 8B0E[0000] mov cx,word ptr [netbios] 0 00005ADF E8[0000] call return_CX 80 f5E_success: 0 00005AE2 31C0 xor ax,ax ; return zero 0 00005AE4 E9[0000] jmp return_AX_CLC 83 84 ; 85 ; Set the Network Name 86 ; 87 f5E01: 88 ; mov name_num,ch ; Get the Network and NetBios Nos. 89 ; mov netbios,cl ; and save in local variables 0 00005AE7 890E[0000] mov word ptr [netbios],cx 0 00005AEB FE06[0000] inc byte [net_set_count] 0 00005AEF 1E push ds 0 00005AF0 06 push es 0 00005AF1 1F pop ds 0 00005AF2 07 pop es ; Copy the specified name 0 00005AF3 89D6 mov si,dx ; to internal save area 0 00005AF5 BF[0000] mov di,offset net_name 0 00005AF8 B90F00 mov cx,15 ; Copy 15 byte name leave 0 00005AFB F3A4 rep movsb ; Terminating 00 0 00005AFD 06 push es 0 00005AFE 1F pop ds 0 00005AFF EBE1 jmp f5E_success 103 104 105 ; ***************************** 106 ; *** DOS Function 5F *** 107 ; *** Network Control *** 108 ; ***************************** 109 ; 110 Public func5F 111 func5F: 0 00005B01 3C07 cmp al,07h 0 00005B03 7404 je func5F_10 0 00005B05 3C08 cmp al,08h 0 00005B07 7526 jne func5F_40 116 func5F_10: 0 00005B09 50 push ax 0 00005B0A 88D0 mov al,dl 0 00005B0C E8[0000] call get_ldt_raw 0 00005B0F 58 pop ax 0 00005B10 7215 jc func5F_30 0 00005B12 26837F4501 cmp word ptr [es:LDT_PDT + bx],1 0 00005B17 720E jb func5F_30 0 00005B19 26804F4440 or byte ptr [es:LDT_FLAGS+1 + bx],(LFLG_PHYSICAL >> 8) & 0ffh 0 00005B1E 3C07 cmp al,07h 0 00005B20 7405 je func5F_30 0 00005B22 26806744BF and byte ptr [es:LDT_FLAGS+1 + bx],((~ LFLG_PHYSICAL) >> 8) & 0ffh 128 func5F_30: 0 00005B27 731A jnc func5F_OK 0 00005B29 B8F1FF mov ax,ED_DRIVE 0 00005B2C E9[0000] jmp error_exit 132 133 func5F_40: 0 00005B2F B81E11 mov ax,I2F_REDIR_5F ; magic int 2F number 135 136 Public func5F_common 137 func5F_common: 0 00005B32 1E push ds 0 00005B33 FF36[0000] push word [int21AX] ; AX passed on the stack.. 0 00005B37 06 push es 0 00005B38 E8[0000] call reload_ES ; get the segment registers 0 00005B3B 1F pop ds ; back to entry state 0 00005B3C F9 stc ; assume it will fail 0 00005B3D CD2F int 2fh ; pass it on to MSNET 0 00005B3F 1F pop ds ; throw away word on the stack 0 00005B40 1F pop ds 0 00005B41 7203 jc func5F_error 148 func5F_OK: 0 00005B43 E9[0000] jmp return_AX_CLC ; return the result 150 func5F_error: 0 00005B46 F7D8 neg ax ; our error convention is negative.. 0 00005B48 E9[0000] jmp error_exit ; Error for all sub functions 153 154 PCM_CODE ends 155 === Switch to base=00C180h -> "PCMODE_DATA" 156 section PCMODE_DATA public align=2 class=DATA 157 158 extrn net_name:byte 159 extrn net_set_count:byte 160 extrn name_num:byte 161 extrn netbios:byte 162 extrn int21AX:word 163 164 PCMODE_DATA ends 165 166 end === Trace listing source: drdos/bin/int2f.lst 1 ; File : $INT2F.ASM$ 2 ; 3 ; Description : 4 ; 5 ; Original Author : 6 ; 7 ; Last Edited By : $Author$ 8 ; 9 ;-----------------------------------------------------------------------; 10 ; Copyright Work of Caldera, Inc. All Rights Reserved. 11 ; 12 ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, 13 ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. 14 ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES 15 ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF 16 ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO 17 ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE 18 ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE 19 ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, 20 ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, 21 ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, 22 ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF 23 ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT 24 ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND 25 ; CIVIL LIABILITY. 26 ;-----------------------------------------------------------------------; 27 ; 28 ; *** Current Edit History *** 29 ; *** End of Current Edit History *** 30 ; 31 ; $Log$ 32 ; INT2F.A86 1.23 94/11/14 10:34:17 33 ; Fixed the NWDOS.386 stuff. Still point at startupinfo, but take out the 34 ; vxdname and the vxdnameseg entries. 35 ; INT2F.A86 1.22 94/10/07 09:05:11 36 ; Added patch 005 as source fix. Removed the stuff to load NWDOS.386 as 37 ; the vxd is no longer needed. 38 ; INT2F.A86 1.21 94/03/24 18:40:10 39 ; Support para-aligned HMA allocations (Stacker 4 bug) 40 ; INT2F.A86 1.20 93/09/28 19:43:12 41 ; Extra field to export upper memory root on windows startup 42 ; INT2F.A86 1.19 93/09/06 15:37:35 43 ; Startup Broadcast fills entry ES:BX into SwStartupInfo "next" link field 44 ; INT2F.A86 1.16 93/08/06 16:35:58 45 ; Change DELWATCH int 2F hook for getnblk to getblk 46 ; INT2F.A86 1.15 93/07/20 22:47:21 47 ; Pass on Int 2F/12FF to BIOS - (really to CONFIG) 48 ; INT2F.A86 1.11 93/06/11 02:10:01 49 ; GateA20 disabled on EXEC for EXEPACKED apps 50 ; ENDLOG 51 ; 52 ; DOS INT 2F Support 53 ; 54 55 group PCMCODE PCM_CODE 56 group PCMDATA PCMODE_DATA FDOS_DSEG GLOBAL_DATA 57 58 ASSUME DS:PCMDATA 59 60 [list -] 69 === Switch to base=000000h -> "PCM_CODE" 70 section PCM_CODE public align=1 class=CODE 71 72 extrn get_dseg:near ; in PCMIF.PCM 73 extrn do_int24:near ; in PCMIF.PCM 74 extrn dos_entry:near 75 extrn strlen:near ; in SUPPORT.PCM 76 extrn toupper:near ; in UTILS.FDO (in BDOS_CODE) 77 extrn ReadTOD:near ; in UTILS.FDO (in BDOS_CODE) 78 extrn share_delay:near ; in UTILS.FDO (in BDOS_CODE) 79 80 81 PointHMA: 82 ;-------- 83 ; On Entry: 84 ; None 85 ; On Exit: 86 ; DS = DOS data seg 87 ; BX = bytes available (0 if none) 88 ; ES:DI -> start of available area (FFFF:FFFF if none) 89 ; All other regs preserved 90 ; 0 00005B4B E8[0000] call get_dseg ; DS = DOS data 0 00005B4E BFFFFF mov di,0FFFFh 0 00005B51 8EC7 mov es,di ; ES:DI = FFFF:FFFF 0 00005B53 8B1E[0000] mov bx,[hmaRoot] 0 00005B57 85DB test bx,bx ; have we an HMA ? 0 00005B59 740C jz PointHMA10 0 00005B5B 89DF mov di,bx ; ES:DI = start of HMA free area 0 00005B5D 268B5F02 mov bx,[es:2 + bx] ; BX = length 0 00005B61 83EB04 sub bx,4 ; forget the header 0 00005B64 80E3F0 and bl,~ 15 ; make it complete para's 101 PointHMA10: 0 00005B67 C3 ret 103 104 QueryHMA: 105 ;-------- 106 ; On Entry: 107 ; None 108 ; On Exit: 109 ; BX = bytes available (0 if none) 110 ; ES:DI -> start of available area (FFFF:FFFF if none) 111 ; All other regs preserved 112 ; 0 00005B68 1E push ds 0 00005B69 E8DFFF call PointHMA ; registers ready for return 0 00005B6C EB60 jmp int2F_BIOS ; give CONFIG processing a chance 116 117 118 AllocHMA: 119 ;-------- 120 ; On Entry: 121 ; BX = bytes required 122 ; On Exit: 123 ; ES:DI -> start of available area (FFFF:FFFF if none) 124 ; 0 00005B6E 1E push ds 0 00005B6F 93 xchg ax,bx ; AX = bytes required 0 00005B70 83C00F add ax,15 0 00005B73 24F0 and al,~ 15 ; round up to para's 0 00005B75 E8D3FF call PointHMA 0 00005B78 93 xchg ax,bx 0 00005B79 39D8 cmp ax,bx ; enough room up there ? 0 00005B7B 7304 jae AllocHMA10 0 00005B7D 8CC7 mov di,es ; ES:DI = FFFF:FFFF 0 00005B7F EB1C jmp AllocHMA20 135 AllocHMA10: 0 00005B81 011E[0000] add [hmaRoot],bx ; set new start 0 00005B85 268B4502 mov ax,[es:2 + di] ; get length 0 00005B89 29D8 sub ax,bx ; subtract what we just allocated 0 00005B8B 26894102 mov [es:2 + di+bx],ax ; set new length 0 00005B8F 83F804 cmp ax,4 ; have we shrunk to zero spare ? 0 00005B92 268B05 mov ax,[es:di] ; move link field to 0 00005B95 268901 mov [es:di+bx],ax ; new head 0 00005B98 7703 ja AllocHMA20 0 00005B9A A3[0000] mov [hmaRoot],ax ; set new hmaRoot 145 AllocHMA20: 0 00005B9D B8024A mov ax,4A02h ; "restore" AX 0 00005BA0 1F pop ds 0 00005BA1 CF iret 149 150 ; ++++++++++++++++++++++++++++ 151 ; Int 2F - Multiplex Interrupt 152 ; ++++++++++++++++++++++++++++ 153 ; 154 ; This interrupt is used by DBASE III Plus 155 ; 156 ; On Entry:- AH - Multi-Plex Number 157 ; 01 - Print Spooler 158 ; 02 - Assign Command (Documented) 159 ; 05 - Critical Error Msg 160 ; 06 - Assign Command (By Inspection) 161 ; 08 - DRIVER.SYS Interface for MS-DOS 3.xx 162 ; 10 - Share Command 163 ; 11 - Internal DOS - Network Hooks 164 ; 12 - Internal DOS - Support Services 165 ; 13 - Original INT 13 ROS ISR Address (BIOS) 166 ; 14 - NLSFUNC utility 167 ; AD - IBM CodePage Screen Driver 168 ; B7 - Append Command 169 ; B8 - Network Command 170 ; 171 ; AL - Function Code 172 ; 00 - Get Installed State (All) 173 ; 01 - Submit File (PRINT) 174 ; 02 - Cancel File (PRINT) 175 ; 03 - Cancel All Files (PRINT) 176 ; 04 - Spooler Status (PRINT) 177 ; 05 - End of Status (PRINT) 178 ; 179 ; The Network Test returns the current Network configuration in 180 ; BX when the Get Installed State is requested. 181 ; 182 ; BX = 0008h Redirector | Increasing 183 ; BX = 0080h Receiver | Network 184 ; BX = 0004h Messenger | Functionality 185 ; BX = 0040h Server V 186 ; 187 Public int2F_entry 188 189 int2F_entry: 0 00005BA2 FB sti 0 00005BA3 FC cld 0 00005BA4 80FC12 cmp ah,012h 0 00005BA7 7451 je i2f_12 ; intercept the AH=12 subfunctions 0 00005BA9 80FC11 cmp ah,011h 0 00005BAC 7441 je i2f_11 ; intercept the AH=11 subfunctions 0 00005BAE 80FC10 cmp ah,010h 0 00005BB1 7423 je i2f_10 ; intercept the AH=10 subfunctions 0 00005BB3 80FC05 cmp ah,005h 0 00005BB6 741A je i2f_05 ; intercept the AH=05 subfunctions 0 00005BB8 3D014A cmp ax,4A01h 0 00005BBB 74AB je QueryHMA ; intercept Query Free HMA Space 0 00005BBD 3D024A cmp ax,4A02h 0 00005BC0 74AC je AllocHMA ; intercept Allocate HMA space 0 00005BC2 80FC16 cmp ah,016h 0 00005BC5 7503 jne int2F_exit ; intercept the AH=16 subfucntions 0 00005BC7 E9D603 jmp WindowsHooks ; go do windows things... 207 int2F_exit: 0 00005BCA 1E push ds ; pass onto BIOS now 0 00005BCB E8[0000] call get_dseg ; trying to remain ROMMABLE 210 int2F_BIOS: 0 00005BCE FF2E[0000] jmp far [int2FNext] ; hence this complication 212 213 214 i2f_05: 215 ;------ 216 ; CRITICAL ERROR MSG 217 ; This is the critical error message interceptor. 218 ; On Entry: AL = extended error code. 219 ; On Exit: if CY clear then ES:DI -> ASCIIZ string to be used in place 220 ; of the default error message 0 00005BD2 F9 stc ; please use the default message 0 00005BD3 CA0200 retf 2 ; IRET, but keep flags 223 224 225 i2f_10: 226 ;------ 227 ; SHARE 0 00005BD6 3C0A cmp al,i2f_10size ; do we do this one ? 0 00005BD8 73F0 jae int2F_exit ; no, skip it 0 00005BDA D0E0 shl al,1 ; we need a word offset 0 00005BDC 74EC jz int2F_exit ; exit if share installation check 0 00005BDE 98 cbw ; zero AH 0 00005BDF 93 xchg ax,bx ; we will index with it 0 00005BE0 1E push ds 0 00005BE1 E8[0000] call get_dseg ; get PCMode data seg 0 00005BE4 1E push ds 0 00005BE5 07 pop es 0 00005BE6 2EFF97[2F04] call [cs:i2f_10tbl + bx] ; execute the function 0 00005BEB 1F pop ds 0 00005BEC CA0200 retf 2 ; and return 241 242 i2f_11: 243 ;------ 244 ; MSNET redirector 0 00005BEF 84C0 test al,al ; is it installation check ? 0 00005BF1 7404 jz i2f_11_10 0 00005BF3 B80100 mov ax,1 ; no, return ED_FUNCTION error 0 00005BF6 F9 stc ; indicate an error 249 i2f_11_10: 0 00005BF7 CA0200 retf 2 ; return 251 252 i2f_12: 253 ;------ 254 ; DOS Internal 255 ; Support DOS internal functions here 0 00005BFA 3CFF cmp al,0FFh ; should we pass it on to the BIOS ? 0 00005BFC 74CC je int2F_exit ; yes, do so 0 00005BFE 3C2E cmp al,i2f_12size ; do we do this one ? 0 00005C00 7314 jae i2f_12_bad ; no, skip it 0 00005C02 55 push bp 0 00005C03 30E4 xor ah,ah 0 00005C05 01C0 add ax,ax ; make sub-func a word 0 00005C07 89C5 mov bp,ax ; we need offset in pointer register 0 00005C09 2E8B86[D200] mov ax,[cs:i2f_12tbl + bp] ; get address of service routine 0 00005C0E 89E5 mov bp,sp ; BP points to stack frame 0 00005C10 FFD0 call ax ; call the service routine 0 00005C12 5D pop bp 268 i2f_12_exit: 0 00005C13 CA0200 retf 2 ; IRET, but returning flags 270 i2f_12_bad: 0 00005C16 B80100 mov ax,-ED_FUNCTION 0 00005C19 F9 stc 0 00005C1A CA0200 retf 2 274 275 0 00005C1D [2F01] i2f_12tbl dw i2f_1200 0 00005C1F [3301] dw i2f_1201 0 00005C21 [4601] dw i2f_1202 0 00005C23 [5201] dw i2f_1203 0 00005C25 [5501] dw i2f_1204 0 00005C27 [6101] dw i2f_1205 0 00005C29 [6C01] dw i2f_1206 0 00005C2B [2E01] dw i2f_12nyi ; Move disk buffer 0 00005C2D [8401] dw i2f_1208 0 00005C2F [2E01] dw i2f_12nyi ; DS:DI -> Disk Buffer ?? 0 00005C31 [8D01] dw i2f_120A 0 00005C33 [A101] dw i2f_120B 0 00005C35 [A601] dw i2f_120C 0 00005C37 [B901] dw i2f_120D 0 00005C39 [0000] dw share_delay ; delay 0 00005C3B [2E01] dw i2f_12nyi ; relink buffer ES:DI ([DI+5].20 <- 0) - Trout 0 00005C3D [CB01] dw i2f_1210 0 00005C3F [CE01] dw i2f_1211 0 00005C41 [DE01] dw i2f_1212 0 00005C43 [EA01] dw i2f_1213 0 00005C45 [F001] dw i2f_1214 0 00005C47 [2E01] dw i2f_12nyi ; Disk buffer DS:SI ??? (Write - Trout) 0 00005C49 [FF01] dw i2f_1216 0 00005C4B [2C02] dw i2f_1217 0 00005C4D [5802] dw i2f_1218 0 00005C4F [6002] dw i2f_1219 0 00005C51 [8902] dw i2f_121A 0 00005C53 [AF02] dw i2f_121B 0 00005C55 [C502] dw i2f_121C 0 00005C57 [CF02] dw i2f_121D 0 00005C59 [DD02] dw i2f_121E 0 00005C5B [0C03] dw i2f_121F 0 00005C5D [5B03] dw i2f_1220 0 00005C5F [7703] dw i2f_1221 0 00005C61 [8203] dw i2f_1222 0 00005C63 [AB03] dw i2f_1223 0 00005C65 [0000] dw share_delay 0 00005C67 [E903] dw i2f_1225 0 00005C69 [F103] dw i2f_1226 0 00005C6B [0104] dw i2f_1227 0 00005C6D [0504] dw i2f_1228 0 00005C6F [0C04] dw i2f_1229 0 00005C71 [1004] dw i2f_122A 0 00005C73 [1804] dw i2f_122B 0 00005C75 [1F04] dw i2f_122C 0 00005C77 [2B04] dw i2f_122D 322 i2f_12size equ ((offset $) - (offset i2f_12tbl))/2 323 324 i2f_12nyi: 325 ; Sets CY the falls through to installation check - so returns ax = 00FF 326 ; Who knows what to do ? 0 00005C79 F9 stc ; indicate problem ? 328 329 i2f_1200: 0 00005C7A B8FF00 mov ax,00FFh 0 00005C7D C3 ret 332 333 i2f_1201: 334 ; Close file ??? (at current_dhndl) 0 00005C7E C43E[0000] les di,[current_dhndl] 0 00005C82 268B5D05 mov bx,[es:DHNDL_WATTR + di] 0 00005C86 F6C780 test bh,DHAT_REMOTE/100h 0 00005C89 7405 jz i2f_1201_10 ; is it networked ? 0 00005C8B B80611 mov ax,I2F_CLOSE 0 00005C8E CD2F int 2fh ; then close using int 2f call 341 i2f_1201_10: ; else do nothing for now 0 00005C90 C3 ret 343 344 i2f_1202: 345 ; Get Interrupt Vector pointer 0 00005C91 31DB xor bx,bx 0 00005C93 8EC3 mov es,bx ; point at the vectors 0 00005C95 8A5E08 mov bl,[8 + bp] ; pick up which vector 0 00005C98 01DB add bx,bx 0 00005C9A 01DB add bx,bx ; make it a DWORD offset 0 00005C9C C3 ret 352 353 i2f_1203: 354 ; Get DOS Data segment 0 00005C9D E9[0000] jmp get_dseg ; return DS = DOS data seg 356 357 i2f_1204: 358 ; Normalise path character 0 00005CA0 8B4608 mov ax,[8 + bp] ; the char is on the stack 360 tobslash: 0 00005CA3 3C2F cmp al,'/' ; if it's a fslash 0 00005CA5 7502 jne i2f_1204_10 0 00005CA7 B05C mov al,'\' ; make it a bslash 364 i2f_1204_10: 0 00005CA9 3C5C cmp al,'\' ; set ZF if bslash 0 00005CAB C3 ret 367 368 i2f_1205: 369 ; Output Character on the stack 0 00005CAC 52 push dx 0 00005CAD B402 mov ah,MS_C_WRITE 0 00005CAF 8B5608 mov dx,[8 + bp] ; get char from the stack 0 00005CB2 E8[0000] call dos_entry ; and output it 0 00005CB5 5A pop dx 0 00005CB6 C3 ret 376 377 i2f_1206: 378 ; Invoke critical error INT 24 0 00005CB7 1E push ds 0 00005CB8 8B4608 mov ax,[8 + bp] ; action/drive on stack 0 00005CBB 8E4600 mov es,[0 + bp] ; seg was in BP 0 00005CBE E8[0000] call get_dseg ; get the segment right 0 00005CC1 E8[0000] call do_int24 ; invoke the critical error handler 0 00005CC4 50 push ax 0 00005CC5 C406[0000] les ax,[int24_esbp] 0 00005CC9 894600 mov [bp],ax ; really return new BP 0 00005CCC 58 pop ax 0 00005CCD 1F pop ds 0 00005CCE C3 ret 390 391 i2f_1208: 392 ; Decrement word at ES:DI, skipping zero 0 00005CCF 268B05 mov ax,word ptr [es:di] ; return the word in AX 394 i2f_1208_10: 0 00005CD2 26FF0D dec word ptr [es:di] ; dec it 0 00005CD5 74FB jz i2f_1208_10 ; dec again if it's zero 0 00005CD7 C3 ret 398 399 i2f_120A: 0 00005CD8 1E push ds 0 00005CD9 C536[0000] lds si,[current_ddsc] ; point at current driver 0 00005CDD AC lodsb ; get the drive 0 00005CDE 98 cbw ; pretend dos area read 0 00005CDF 1F pop ds 0 00005CE0 A2[0000] mov [err_drv],al 0 00005CE3 8826[0000] mov [rwmode],ah ; set error drive for Int 24h 0 00005CE7 B80300 mov ax,3 ; return a Fail ? 0 00005CEA F9 stc ; return as error 0 00005CEB C3 ret 410 411 i2f_120B: 412 ; ES:DI -> system file table entry 0 00005CEC B82000 mov ax,20h ; sharing violation 0 00005CEF F9 stc ; return as error 0 00005CF0 C3 ret 416 417 i2f_120C: 418 ; Open file ??? (at current_dhndl) 0 00005CF1 C43E[0000] les di,[current_dhndl] 420 ; would need to call the device driver, but as we don't support this for 421 ; block devices and as it is generally not supported for remote files (but 422 ; only known to be called from redirectors) we leave this out for later 0 00005CF5 26F6450380 test byte ptr [es:DHNDL_MODE+1 + di],DHM_FCB/100h 0 00005CFA 7407 jz i2f_120C_10 ; is it an FCB open ? 0 00005CFC A1[0000] mov ax,[current_psp] 0 00005CFF 26894531 mov [es:DHNDL_PSP + di],ax ; update owning PSP field 427 i2f_120C_10: ; else do nothing for now 0 00005D03 C3 ret 429 430 i2f_120D: 431 ; Get Date/Time 0 00005D04 1E push ds 0 00005D05 06 push es 0 00005D06 51 push cx 0 00005D07 53 push bx 0 00005D08 56 push si 0 00005D09 57 push di 0 00005D0A 16 push ss 0 00005D0B 1F pop ds 0 00005D0C E8[0000] call ReadTOD 0 00005D0F 5F pop di 0 00005D10 5E pop si 0 00005D11 5B pop bx 0 00005D12 59 pop cx 0 00005D13 07 pop es 0 00005D14 1F pop ds 0 00005D15 C3 ret 448 449 450 i2f_1210: 451 ; Find Dirty Buffer Entry DS:SI -> 1st buffer, On exit DS:SI-> 1st dirty buffer 452 ; ZF set if none found 0 00005D16 31C0 xor ax,ax ; never find dirty buffers 0 00005D18 C3 ret 455 456 i2f_1211: 457 ; Normalise ASCIIZ filename DS:SI -> source buffer, ES:DI -> dest buffer 458 ; make uppercase, fslash becomes bslash 459 ; (Stops at slash - Trout) 0 00005D19 AC lodsb ; get a character 0 00005D1A E8[0000] call toupper ; upper case it 0 00005D1D E883FF call tobslash ; convert '/' to '\' 0 00005D20 AA stosb ; plant it 0 00005D21 84C0 test al,al ; terminating zero ? 0 00005D23 75F4 jnz i2f_1211 0 00005D25 8B4608 mov ax,[8 + bp] ; AX from stack 0 00005D28 C3 ret 468 469 i2f_1212: 470 ; Get length of ASCIIZ string ES:DI 0 00005D29 1E push ds 0 00005D2A 56 push si 0 00005D2B 06 push es 0 00005D2C 1F pop ds 0 00005D2D 89FE mov si,di ; make DS:SI -> ASCIIZ 0 00005D2F E80202 call i2f_1225 ; then use our other primitive 0 00005D32 5E pop si 0 00005D33 1F pop ds 0 00005D34 C3 ret 480 481 i2f_1213: 482 ; Upperase character on stack 0 00005D35 8B4608 mov ax,[8 + bp] ; get the character 0 00005D38 E9[0000] jmp toupper ; use BDOS Intl routine 485 486 i2f_1214: 487 ; Compare far pointers DS:SI with ES:DI 0 00005D3B 39F7 cmp di,si 0 00005D3D 750A jne i2f_1214_10 0 00005D3F 50 push ax 0 00005D40 53 push bx 0 00005D41 8CD8 mov ax,ds 0 00005D43 8CC3 mov bx,es 0 00005D45 39D8 cmp ax,bx 0 00005D47 5B pop bx 0 00005D48 58 pop ax 497 i2f_1214_10: 0 00005D49 C3 ret 499 500 i2f_1216: 501 ; Get address in ES:DI of DOSHNDL for file BX 0 00005D4A 1E push ds 0 00005D4B E8[0000] call get_dseg ; we work with the PCMODE data 0 00005D4E C43E[0000] les di,[file_ptr] ; get the address of the first entry 0 00005D52 1F pop ds 0 00005D53 53 push bx ; handle # in BX 507 i2f_1216_10: 0 00005D54 263B5D04 cmp bx,[es:DCNTRL_COUNT + di] ; handle in this block? 0 00005D58 720F jb i2f_1216_20 ; skip if yes 0 00005D5A 262B5D04 sub bx,[es:DCNTRL_COUNT + di] ; update the internal file number 0 00005D5E 26C43D les di,[es:DCNTRL_DSADD + di] ; get the next entry and check 0 00005D61 83FFFF cmp di,0FFFFh ; for the end of the list 0 00005D64 75EE jnz i2f_1216_10 0 00005D66 58 pop ax ; handle # back in AX 0 00005D67 F9 stc ; invalid file handle number 0 00005D68 C3 ret 517 518 i2f_1216_20: 0 00005D69 52 push dx ; save DX and calculate the offset 0 00005D6A B84B00 mov ax,DHNDL_LEN ; of the DOS Handle 0 00005D6D F7E3 mul bx 0 00005D6F 01C7 add di,ax ; add structure offset (should be 0) 0 00005D71 83C706 add di,DCNTRL_LEN ; and then skip the header 0 00005D74 5A pop dx 0 00005D75 58 pop ax ; handle # back in AX 526 ; clc 0 00005D76 C3 ret ; valid file handle number 528 529 i2f_1217: 530 ; Default Drive ??? 531 ; On Exit: 532 ; AL = drive we have set to, DS:SI -> LDT structure 0 00005D77 E8[0000] call get_dseg ; DS -> PCMODE data 0 00005D7A 8B4608 mov ax,[8 + bp] ; get the drive 0 00005D7D 3A06[0000] cmp al,[last_drv] ; do we have an LDT for it ? 0 00005D81 731E jae i2f_1217_10 ; if not do no more 0 00005D83 833E[0200]00 cmp word [ldt_ptr+2],0 ; valid LDT ? 0 00005D88 7417 je i2f_1217_10 0 00005D8A 50 push ax 0 00005D8B B458 mov ah,LDT_LEN 0 00005D8D F6E4 mul ah 0 00005D8F C536[0000] lds si,[ldt_ptr] 0 00005D93 01C6 add si,ax ; DS:SI -> requested LDT, current_LDT 0 00005D95 368936[0000] mov word ptr [ss:current_ldt],si 0 00005D9A 368C1E[0200] mov word ptr [ss:current_ldt+2],ds 0 00005D9F 58 pop ax 0 00005DA0 F9 stc ; indicate NO error (CY inverted) 548 i2f_1217_10: 0 00005DA1 F5 cmc 0 00005DA2 C3 ret ; CY set if invalid 551 552 553 i2f_1218: 554 ; DS:SI -> User register on DOS Call 0 00005DA3 E8[0000] call get_dseg ; we save SS:SP after PUSH$DOS 0 00005DA6 C536[0000] lds si,[int21regs_ptr] ; in this location 0 00005DAA C3 ret 558 559 i2f_1219: 560 ; Stack = drive (0=default, 1 = A: etc) 0 00005DAB 1E push ds 0 00005DAC 56 push si 0 00005DAD FF7608 push word ptr [8 + bp] 0 00005DB0 FE4E08 dec byte ptr [8 + bp] ; make drive zero based 0 00005DB3 807E08FF cmp byte ptr [8 + bp],0ffh ; do we want the default ? 0 00005DB7 7509 jne i2f_1219_10 0 00005DB9 E8[0000] call get_dseg 0 00005DBC A0[0000] mov al,[current_dsk] 0 00005DBF 884608 mov byte ptr [8 + bp],al ; use the default drive 570 i2f_1219_10: 0 00005DC2 E8B2FF call i2f_1217 ; set's up current_ldt 0 00005DC5 7207 jc i2f_1219_20 0 00005DC7 F6444440 test byte ptr [44h + si],40h ; is it valid LDT ? 0 00005DCB 7501 jnz i2f_1219_20 0 00005DCD F9 stc ; indicate an error 576 i2f_1219_20: 0 00005DCE 8F4608 pop word ptr [8 + bp] 0 00005DD1 5E pop si 0 00005DD2 1F pop ds 0 00005DD3 C3 ret 581 582 i2f_121A: 583 ; Get files drive DS:SI -> drives, AL = drive 0 00005DD4 31C0 xor ax,ax ; assume default drive 0 00005DD6 807C013A cmp byte ptr [1 + si],':' 0 00005DDA 7518 jne i2f_121A_10 ; if no drive letter, then default 0 00005DDC 8A04 mov al,byte ptr [si] 0 00005DDE 84C0 test al,al ; null string ? 0 00005DE0 7412 jz i2f_121A_10 ; then it's the default drive 0 00005DE2 E8[0000] call toupper 0 00005DE5 2C40 sub al,'A'-1 ; make one based 0 00005DE7 760D jbe i2f_121A_20 ; it's invalid.. 0 00005DE9 1E push ds 0 00005DEA E8[0000] call get_dseg 0 00005DED 3A06[0000] cmp al,[last_drv] ; is it a valid drive ? 0 00005DF1 1F pop ds 0 00005DF2 7702 ja i2f_121A_20 ; yes, return it 598 i2f_121A_10: 0 00005DF4 F8 clc 0 00005DF5 C3 ret 601 i2f_121A_20: 0 00005DF6 B0FF mov al,0FFh ; invalid drive 0 00005DF8 F9 stc 0 00005DF9 C3 ret 605 606 i2f_121B: 607 ; On Entry CX = year-1980 608 ; On Exit AL = days in February 0 00005DFA 53 push bx 0 00005DFB BB[0100] mov bx,offset days_in_month+1 0 00005DFE C6071C mov byte ptr [bx],28 ; assume 28 days in Feb 0 00005E01 F6C103 test cl,3 ; is it a leap year ? 0 00005E04 7502 jnz i2f_121B_10 0 00005E06 FE07 inc byte ptr [bx] ; yes, we have 29 615 i2f_121B_10: 0 00005E08 880E[0000] mov [yearsSince1980],cl ; save the year 0 00005E0C 8A07 mov al,byte ptr [bx] ; return the days in Feb 0 00005E0E 5B pop bx 0 00005E0F C3 ret 620 621 i2f_121C: 622 ; Checksum Memory CX bytes at DS:SI, DX = initial checksum 623 ; DX = final checksum 624 ; I've seen this used to total days in N months. 625 ; On Entry: 626 ; CX = current month 627 ; DX = total days in prior years 628 ; DS:SI -> days-per-month table 629 ; On Exit: 630 ; DX = Total days to start of current month 631 ; 0 00005E10 31C0 xor ax,ax ; clear AX 0 00005E12 E305 jcxz i2f_121C_20 ; check for zero bytes 634 i2f_121C_10: 0 00005E14 AC lodsb ; get a byte 0 00005E15 01C2 add dx,ax ; add to the checksum 0 00005E17 E2FB loop i2f_121C_10 ; until we run out 638 i2f_121C_20: 0 00005E19 C3 ret 640 641 i2f_121D: 642 ; Calculate Date 643 ; On Entry: 644 ; CX = 0 645 ; DX = total day count this year 646 ; DS:SI -> days-per-month table 647 ; On Exit: 648 ; CX = Month 649 ; DX = Day 650 ; 0 00005E1A 31C0 xor ax,ax 652 i2f_121D_10: 0 00005E1C AC lodsb 0 00005E1D 41 inc cx 0 00005E1E 29C2 sub dx,ax 0 00005E20 73FA jnb i2f_121D_10 0 00005E22 49 dec cx ; undo the last count 0 00005E23 01C2 add dx,ax ; undo the sub 0 00005E25 39C2 cmp dx,ax ; get the flags right 0 00005E27 C3 ret 661 662 i2f_121E: 663 ; Compare Filenames at DS:SI and ES:DI 0 00005E28 56 push si 0 00005E29 57 push di 0 00005E2A 51 push cx 0 00005E2B E80601 call i2f_1225 ; find length of DS:SI filename 0 00005E2E 51 push cx 0 00005E2F E8F7FE call i2f_1212 ; find length of ES:DI filename 0 00005E32 58 pop ax 0 00005E33 39C8 cmp ax,cx ; if lengths not the same 0 00005E35 7519 jne i2f_121E_20 ; don't even bother 673 i2f_121E_10: 0 00005E37 51 push cx 0 00005E38 AC lodsb 0 00005E39 E8[0000] call toupper 0 00005E3C E864FE call tobslash ; normalise slash characters 0 00005E3F 50 push ax ; save it 0 00005E40 268A05 mov al,byte ptr [es:di] 0 00005E43 47 inc di 0 00005E44 E8[0000] call toupper 0 00005E47 E859FE call tobslash ; normalise slash again 0 00005E4A 59 pop cx ; recover the character 0 00005E4B 38C8 cmp al,cl ; are they the same? 0 00005E4D 59 pop cx 0 00005E4E E1E7 loope i2f_121E_10 ; yes, try again if we have any left 687 i2f_121E_20: 0 00005E50 59 pop cx 0 00005E51 5F pop di 0 00005E52 5E pop si 0 00005E53 8B4608 mov ax,[8 + bp] ; return stack value in AX 0 00005E56 C3 ret 693 694 i2f_121F: 695 ; Build drive info into block 696 ; Stack = Drive (1=A: etc) 0 00005E57 1E push ds 0 00005E58 56 push si 0 00005E59 52 push dx 0 00005E5A E8[0000] call get_dseg 0 00005E5D C43E[0000] les di,[current_ldt] 0 00005E61 57 push di 0 00005E62 8B4608 mov ax,[8 + bp] ; get the drive we want to do 0 00005E65 AA stosb ; plant the ASCII 0 00005E66 92 xchg ax,dx ; save drive in DX 0 00005E67 B83A5C mov ax,':\' ; NASM port swapped text literals 0 00005E6A AB stosw ; we have d:\. 0 00005E6B 31C0 xor ax,ax 0 00005E6D B94000 mov cx,LDT_FLAGS-3 0 00005E70 F3AA rep stosb ; zero rest of name and flags 711 ; lea di,LDT_FLAGS 0 00005E72 80E21F and dl,1fh ; convert from ASCII 0 00005E75 4A dec dx ; into zero based drive number 0 00005E76 3A16[0000] cmp dl,[phys_drv] ; valid physical drive ? 0 00005E7A 7303 jae i2f_121F_10 ; mark it as such 0 00005E7C B80040 mov ax,LFLG_PHYSICAL 717 i2f_121F_10: 0 00005E7F AB stosw ; set flags 719 ; lea di,LDT_PDT 0 00005E80 8D36[E8FF] lea si,[ddsc_ptr-18h] 721 i2f_121F_20: 0 00005E84 C57418 lds si,[18h + si] 0 00005E87 83FEFF cmp si,-1 0 00005E8A 7404 je i2f_121F_30 0 00005E8C 3A14 cmp dl,[si] ; is this the DDSC for the drive 0 00005E8E 75F4 jne i2f_121F_20 ; if so save it away 727 i2f_121F_30: 0 00005E90 96 xchg ax,si ; AX = DDSC offset 0 00005E91 AB stosw 0 00005E92 8CD8 mov ax,ds ; AX = DDSC seg 0 00005E94 AB stosw 0 00005E95 B8FFFF mov ax,0FFFFh ; AX = FFFF 0 00005E98 AB stosw 0 00005E99 AB stosw 0 00005E9A AB stosw ; fill in block info 736 ; stosw ! stosw 737 ; lea di,LDT_ROOTLEN 0 00005E9B B80200 mov ax,2 0 00005E9E AB stosw ; set root length 740 ; lea di,LDT_BLKH 0 00005E9F AB stosw 742 ; lea di,LDT_ROOTH 0 00005EA0 AB stosw 0 00005EA1 5F pop di 0 00005EA2 5A pop dx 0 00005EA3 5E pop si 0 00005EA4 1F pop ds 0 00005EA5 C3 ret 749 750 i2f_1220: 751 ; Get pointer to system file table number for handle BX into ES:DI 0 00005EA6 1E push ds 0 00005EA7 E8[0000] call get_dseg 0 00005EAA 8E06[0000] mov es,[current_psp] 0 00005EAE B80600 mov ax,6 ; assume illegal 0 00005EB1 263B1E3200 cmp bx,[es:PSP_XFNMAX] ; is it a legal handle 0 00005EB6 F5 cmc ; invert CY for error return 0 00005EB7 7207 jc i2f_1220_10 ; no, forget it 0 00005EB9 26C43E3400 les di,[es:PSP_XFTPTR] ; get XFT from PSP 0 00005EBE 01DF add di,bx ; add in the offset 761 ; clc 762 i2f_1220_10: 0 00005EC0 1F pop ds 0 00005EC1 C3 ret 765 766 i2f_1221: 0 00005EC2 B460 mov ah,MS_X_EXPAND ; let the FDOS do the walking... 0 00005EC4 E87900 call DOS ; and call our internal entry point 0 00005EC7 7303 jnc i2f_1221_10 0 00005EC9 F7D8 neg ax ; get error code correct 0 00005ECB F9 stc ; before returning error 772 i2f_1221_10: 0 00005ECC C3 ret 774 775 i2f_1222: 776 ; Store error class, locus, action from DS:SI 777 i2f_1222_10: 0 00005ECD AD lodsw 0 00005ECE 3A06[0000] cmp al,byte ptr [error_code] ; have we found the error ? 0 00005ED2 7407 je i2f_1222_20 0 00005ED4 FEC0 inc al ; or hit the end of the list ? 0 00005ED6 7403 jz i2f_1222_20 0 00005ED8 AD lodsw ; skip this one 0 00005ED9 EBF2 jmp i2f_1222_10 ; and try the next 785 i2f_1222_20: 0 00005EDB 80FCFF cmp ah,0ffh ; valid error class ? 0 00005EDE 7404 je i2f_1222_30 0 00005EE0 8826[0000] mov [error_class],ah 789 i2f_1222_30: 0 00005EE4 AD lodsw 0 00005EE5 3CFF cmp al,0ffh 0 00005EE7 7403 je i2f_1222_40 0 00005EE9 A2[0000] mov [error_action],al 794 i2f_1222_40: 0 00005EEC 80FCFF cmp ah,0ffh 0 00005EEF 7404 je i2f_1222_50 0 00005EF1 8826[0000] mov [error_locus],ah 798 i2f_1222_50: 0 00005EF5 C3 ret 800 801 i2f_1223: 802 ; On Entry buffer at 4E6 filled with Device name - eg. "NAME1 " 803 ; Preserve word ptr [4E6] 804 ; if byte ptr [4E6] = 5 then byte ptr [4E6] = E5 805 ; if byte ptr [506] & 8 then exit now with STC 806 ; otherwise work down device chain 807 ; Find device driver for device NAME1 808 ; Check if character device 0 00005EF6 1E push ds 0 00005EF7 E8[0000] call get_dseg 811 %if FALSE 812 push word [name_buf] ; save 1st char of name 813 test magic_byte,8 ; magic location and number ?? 814 jnz i2f_1223_40 ; can we do the check ? 815 cmp byte [name_buf],5 816 jne i2f_1223_10 ; if 1st char is 5, make it 817 mov byte [name_buf],0e5h ; an E5 818 i2f_1223_10: 819 %endif 0 00005EFA BE[0000] mov si,offset nul_device ; start from NUL 821 i2f_1223_20: 822 DEVHDR.ATTRIB equ ATTRIB ; NASM port label 0 00005EFD F744040080 test word [DEVHDR.ATTRIB + si],DA_CHARDEV 0 00005F02 7426 jz i2f_1223_30 ; skip unless character device 0 00005F04 B90800 mov cx,8 0 00005F07 8D3E[0000] lea di,[name_buf] ; point at name we are looking for 0 00005F0B 56 push si 828 DEVHDR.NAM equ NAM ; NASM port label 0 00005F0C 8D740A lea si,[DEVHDR.NAM + si] ; point a device name 0 00005F0F F3A6 repe cmpsb ; compare the names 0 00005F11 5E pop si 0 00005F12 7516 jne i2f_1223_30 ; if we found it, save info 0 00005F14 268936[0000] mov word ptr [es:current_device],si 0 00005F19 268C1E[0200] mov word ptr [es:current_device+2],ds 0 00005F1E 8A7C04 mov bh,byte ptr [DEVHDR.ATTRIB + si] 0 00005F21 80CFE0 or bh,0e0h 0 00005F24 80F720 xor bh,20h ; clear this bit 0 00005F27 F8 clc ; we found it 0 00005F28 EB08 jmp i2f_1223_50 840 i2f_1223_30: 841 DEVHDR.NEXT equ NEXT ; NASM port label 0 00005F2A C534 lds si,[DEVHDR.NEXT + si] 0 00005F2C 83FEFF cmp si,0ffffh ; any more entries ? 0 00005F2F 75CC jne i2f_1223_20 ; yes, do them 845 i2f_1223_40: 0 00005F31 F9 stc 847 i2f_1223_50: 848 %if FALSE 849 pushf 850 call get_dseg ; we may have scambled DS 851 popf 852 pop word [name_buf] ; restore 1st character 853 %endif 0 00005F32 1F pop ds 0 00005F33 C3 ret 856 857 858 i2f_1225: 859 ; Get length of ASCIIZ string DS:SI 0 00005F34 E8[0000] call strlen 0 00005F37 41 inc cx ; include the terminating zero 0 00005F38 8B4608 mov ax,[8 + bp] ; restore AX from stack 0 00005F3B C3 ret 864 865 ; The following are NOT required for MSNET - they are used by NLSFUNC 866 867 i2f_1226: 868 ; Open the file at DS:DX 0 00005F3C 88C8 mov al,cl ; open mode in CL on entry 0 00005F3E B43D mov ah,MS_X_OPEN ; open the file 871 DOS: 0 00005F40 1E push ds 0 00005F41 06 push es 0 00005F42 1F pop ds 0 00005F43 07 pop es 0 00005F44 E8[0000] call dos_entry ; reverse DS/ES before for dos_entry 0 00005F47 1E push ds 0 00005F48 06 push es 0 00005F49 1F pop ds 0 00005F4A 07 pop es 0 00005F4B C3 ret 882 883 i2f_1227: 884 ; Close file BX 0 00005F4C B43E mov ah,MS_X_CLOSE ; close the file 0 00005F4E EBF0 jmp DOS 887 888 i2f_1228: 889 ; LSEEK on file BX 0 00005F50 8B4600 mov ax,[bp] ; seek mode in BP on entry 0 00005F53 B442 mov ah,MS_X_LSEEK ; do the seek 0 00005F55 EBE9 jmp DOS 893 894 i2f_1229: 895 ; Read from file BX 0 00005F57 B43F mov ah,MS_X_READ 0 00005F59 EBE5 jmp DOS 898 899 i2f_122A: 900 ; Set fastopen entry point to DS:SI 901 ; SI = FFFF, sdont't set - just check if installed 0 00005F5B 89F0 mov ax,si ; AX = offset 0 00005F5D 40 inc ax ; AX = 0 if it's an installation check 0 00005F5E F9 stc ; assume it is, and say not installed 0 00005F5F 7501 jne i2f_122A_10 0 00005F61 F8 clc ; fail new installation 907 i2f_122A_10: 0 00005F62 C3 ret 909 910 i2f_122B: 911 ; IOCTL 0 00005F63 8A4600 mov al,[bp] ; get IOCTL minor 0 00005F66 B444 mov ah,MS_X_IOCTL 0 00005F68 EBD6 jmp DOS 915 916 i2f_122C: 917 ; Get 2nd device driver header address 0 00005F6A 1E push ds 0 00005F6B E8[0000] call get_dseg 0 00005F6E C506[0000] lds ax,[nul_device] 0 00005F72 8CDB mov bx,ds ; BX:AX -> 2nd device header 0 00005F74 1F pop ds 0 00005F75 C3 ret 924 925 i2f_122D: 926 ; Get extended error code 0 00005F76 A1[0000] mov ax,[error_code] 0 00005F79 C3 ret 929 930 931 ; 932 ; Our FDOS extentions live here 933 ; 934 %ifdef DELWATCH 935 extrn locate_buffer:near 936 extrn flush_drive:near 937 extrn delfat:near 938 extrn allocate_cluster:near 939 extrn getblk:near 940 extrn change_fat_entry:near 941 extrn fixup_hashing:near 942 943 ; for speed/code size we just call directly in BLACK.A86 944 %endif 945 0 00005F7A [4D04] i2f_10tbl dw i2f_10nyi ; never gets here... 0 00005F7C [4304] dw i2f_1001 ; install fdos hook 948 %ifdef DELWATCH 949 %if FALSE 950 dw i2f_1002 ; read buffer 951 dw i2f_1003 ; flush buffers 952 dw i2f_1004 ; free fat chain 953 dw i2f_1005 ; allocate cluster 954 dw i2f_1006 ; next cluster 955 dw i2f_1007 ; update fat entry 956 dw i2f_1008 ; fixup checksums 957 %else 0 00005F7E [0000] dw locate_buffer ; ask BLACK to find that buffer 0 00005F80 [0000] dw flush_drive ; ask BLACK to flush buffers 0 00005F82 [0000] dw delfat ; ask BLACK to release FAT chain 0 00005F84 [0000] dw allocate_cluster; ask DEBLOCK to allocate space 0 00005F86 [0000] dw getblk ; ask DEBLOCK to return next block 0 00005F88 [0000] dw change_fat_entry; ask DEBLOCK to update fat entry 0 00005F8A [0000] dw fixup_hashing ; ask BLACK to fixup hashing/checksums 965 %endif 0 00005F8C [4E04] dw i2f_1009 ; directory buffer info 967 %endif 968 i2f_10size equ (offset $ - offset i2f_10tbl)/2 969 970 i2f_1001: 971 ;-------- 972 ; install fdos stub 973 ; 974 ; On Entry: 975 ; DX:AX -> new fdos_stub entry address 976 ; On Exit: 977 ; None 978 ; 0 00005F8E E8[0000] call get_dseg ; get PCMode data seg 0 00005F91 A3[0000] mov word ptr [fdos_stub],ax ; fixup our share stubs 0 00005F94 8916[0200] mov word ptr [fdos_stub+2],dx 982 i2f_10nyi: 0 00005F98 C3 ret 984 985 %ifdef DELWATCH 986 %if FALSE 987 988 i2f_1002: 989 ;-------- 990 ; read buffer 991 ; On Entry: 992 ; CH = 0FFh (pre-read required) 993 ; CL = BF_ISFAT/BF_ISDIR/BF_ISDATA 994 ; AH:DX = 24 bit sector number 995 ; On Exit: 996 ; ES:SI -> Buffer control block 997 ; 998 mov al,ah 999 xor ah,ah 1000 jmp locate_buffer 1001 1002 i2f_1003: 1003 ;-------- 1004 ; flush buffers 1005 ; On Entry: 1006 ; AL = drive 1007 ; AH = buffer type to flush (BF_ISFAT+BF_ISDIR+BF_ISDATA) 1008 ; On Exit: 1009 ; None 1010 ; 1011 jmp flush_drive 1012 1013 i2f_1004: 1014 ;-------- 1015 ; free fat chain 1016 ; On Entry: 1017 ; AX = 1st block to release on current drive 1018 ; On Exit: 1019 ; None 1020 xor dx,dx 1021 jmp delfat 1022 1023 i2f_1005: 1024 ;-------- 1025 ; allocate cluster 1026 ; On Entry: 1027 ; AX = block to start search from (eg. current end of file) 1028 ; 0000 = start of disk 1029 ; On Exit: 1030 ; AX = 0000 if none available 1031 ; else allocated block (marked as End Of Chain) 1032 ; 1033 xor dx,dx 1034 jmp allocate_cluster ; ask DEBLOCK.A86 to allocate some space 1035 1036 i2f_1006: 1037 ;-------- 1038 ; get next cluster 1039 ; On Entry: 1040 ; AX = current block 1041 ; On Exit: 1042 ; AX = next block in chain 1043 ; 1044 xor dx,dx 1045 jmp getblk ; ask DEBLOCK.A86 to return next block 1046 1047 i2f_1007: 1048 ;-------- 1049 ; change fat entry 1050 ; On Entry: 1051 ; AX = fat entry to change 1052 ; DX = new value 1053 ; On Exit: 1054 ; None 1055 ; 1056 mov bx,dx 1057 xor dx,dx 1058 xor cx,cx 1059 jmp change_fat_entry ; ask DEBLOCK.A86 to modify FAT entry 1060 1061 i2f_1008: 1062 ;-------- 1063 ; update hash code for directory entry on current drive 1064 ; On Entry: 1065 ; AX = segment of dir buffer 1066 ; CX = cluster to fixup (0 = root) 1067 ; DI = directory entry index(clipped to cluster if subdir) 1068 ; AX:SI-> dir entry (single entry for hashing) 1069 ; On Exit: 1070 ; None 1071 ; 1072 xchg cx,ax 1073 xor dx,dx 1074 jmp fixup_hashing 1075 1076 %endif 1077 1078 i2f_1009: 1079 ;-------- 1080 ; return dirbuf info 1081 ; On Entry: 1082 ; None 1083 ; On Exit: 1084 ; ES:DI -> 128 byte directory record buffer 1085 ; ES:SI -> dir bcb structure 1086 ; 0[si] = drive (FF = invalid) 1087 ; 1[si] = low byte of record number 1088 ; 2[si] = mid byte of record number 1089 ; 3[si] = hi byte of record number 1090 ; 0 00005F99 0E push cs 0 00005F9A 07 pop es 0 00005F9B BE[5404] mov si,offset invalid_dir_bcb 0 00005F9E C3 ret 1095 0 00005F9F FF invalid_dir_bcb db 0ffh ; drive is invalid 1097 ; db ?,?,? ; don't bother about record number 1098 1099 %endif ;DELWATCH 1100 1101 1102 WindowsHooks: 1103 ;------------ 1104 ; On Entry: 1105 ; AH = 16h, it's a windows broadcast 1106 ; AL = subfunction, other regs as appropriate 1107 ; On Exit: 1108 ; Various 1109 ; 0 00005FA0 3C07 cmp al,07h ; 1607: Virtual device init 0 00005FA2 743B je WindowsDOSMGR 0 00005FA4 F7C20100 test dx,1 ; is it a DOSX broadcast ? 0 00005FA8 7508 jnz WindowsExit 0 00005FAA 3C05 cmp al,05h ; 1605: Windows enhanced mode init 0 00005FAC 7405 je WindowsStartup 0 00005FAE 3C06 cmp al,06h ; 1606: Windows enhanced mode exit 0 00005FB0 741D je WindowsShutdown 1118 WindowsExit: 0 00005FB2 CF iret 1120 1121 1122 1123 WindowsStartup: 1124 ;-------------- 0 00005FB3 1E push ds 0 00005FB4 E8[0000] call get_dseg ; DS -> our data 0 00005FB7 FE06[0000] inc byte [criticalSectionEnable] ; enable Int 2Ah for Windows 0 00005FBB FE06[0000] inc byte [WindowsHandleCheck] 1129 1130 ;;if 0 Put this back in, as instance data still required 1131 ;; Removed pointer to vxd in HEADER.A86 BAP 1132 0 00005FBF 891E[0200] mov [SwStartupInfo+2],bx ; Commented out, as NWDOS.386 0 00005FC3 8C06[0400] mov [SwStartupInfo+4],es ; no longer needed. 0 00005FC7 1E push ds 0 00005FC8 07 pop es ; ES -> pcmode data 0 00005FC9 BB[0000] mov bx,offset SwStartupInfo 1138 ;;endif 0 00005FCC E9FFFB jmp int2F_BIOS ; pass on to the BIOS 1140 1141 1142 WindowsShutdown: 1143 ;--------------- 0 00005FCF 1E push ds 0 00005FD0 E8[0000] call get_dseg ; DS -> our data 0 00005FD3 FE0E[0000] dec byte [criticalSectionEnable] ; enable Int 2Ah for Windows 0 00005FD7 FE0E[0000] dec byte [WindowsHandleCheck] 0 00005FDB 1F pop ds 0 00005FDC 29D2 sub dx,dx ; return success 0 00005FDE CF iret 1151 1152 1153 WindowsDOSMGR: 1154 ;------------- 0 00005FDF 83FB15 cmp bx,15h ; is it DOS manager? 0 00005FE2 75CE jne WindowsExit ; forget the others 1157 ; cmp cx,0 0 00005FE4 E30C jcxz WindowsCX0 0 00005FE6 49 dec cx 0 00005FE7 E316 jcxz WindowsCX1 0 00005FE9 49 dec cx 0 00005FEA 49 dec cx 0 00005FEB 49 dec cx 0 00005FEC E31A jcxz WindowsCX4 0 00005FEE 49 dec cx 0 00005FEF E31A jcxz WindowsCX5 0 00005FF1 CF iret 1168 1169 1170 WindowsCX0: 1171 ;---------- 0 00005FF2 1E push ds 0 00005FF3 E8[0000] call get_dseg 0 00005FF6 1E push ds 0 00005FF7 07 pop es ; ES = DOS data segment 0 00005FF8 1F pop ds 0 00005FF9 8D1E[0000] lea bx,[windowsData] ; ES:BX -> secret variables 0 00005FFD 41 inc cx ; tell them we've responded 0 00005FFE CF iret 1180 1181 WindowsCX1: 1182 ;---------- 0 00005FFF 89D3 mov bx,dx ; entry DX=1Fh, exit BX=1Fh 0 00006001 B87CB9 mov ax,0B97Ch ; AX, DX are magic values 0 00006004 BAABA2 mov dx,0A2ABh 1186 ; xor cx,cx ; CX = 0 0 00006007 CF iret 1188 1189 WindowsCX4: 1190 ;---------- 0 00006008 31D2 xor dx,dx 1192 ; xor cx,cx ; CX = 0 0 0000600A CF iret 1194 1195 WindowsCX5: 1196 ;---------- 1197 ; entry: ES:DI -> device driver 1198 ; determine device driver size in bytes 1199 0 0000600B 1E push ds 0 0000600C 85FF test di,di ; not primary DEVICE= driver? 0 0000600E 7521 jnz WindowsCX5NoDev ; can't have DMD preceeding it 0 00006010 8CC0 mov ax,es ; get device segment 0 00006012 48 dec ax ; DMD is one paragraph lower down 0 00006013 8ED8 mov ds,ax ; DS:DI -> device DMD 0 00006015 40 inc ax ; AX = device driver segment 0 00006016 803D44 cmp byte ptr [0 + di],'D' ; see if 'D'device= 0 00006019 7516 jne WindowsCX5NoDev ; skip if not 0 0000601B 3B4501 cmp ax,word ptr [1 + di] ; owned by the driver ? 0 0000601E 7511 jne WindowsCX5NoDev ; skip if not 1211 0 00006020 B81000 mov ax,10h ; bytes per paragraph 0 00006023 F76503 mul word ptr [3 + di] ; bytes in device driver 0 00006026 1F pop ds 0 00006027 89D3 mov bx,dx ; BX = high word 0 00006029 91 xchg ax,cx ; CX = low word 0 0000602A B87CB9 mov ax,0B97Ch ; AX, DX are magic values 0 0000602D BAABA2 mov dx,0A2ABh 0 00006030 CF iret 1220 1221 WindowsCX5NoDev: 1222 ; ES:DI -> not an external device 0 00006031 1F pop ds 0 00006032 31C0 xor ax,ax 0 00006034 31D2 xor dx,dx 1226 ; xor cx,cx ; CX = 0 0 00006036 CF iret 1228 1229 PCM_CODE ends 1230 === Switch to base=00C180h -> "PCMODE_DATA" 1231 section PCMODE_DATA public align=2 class=DATA 1232 extrn hmaRoot:word 1233 extrn last_drv:byte 1234 extrn phys_drv:byte 1235 extrn ddsc_ptr:dword 1236 extrn current_psp:word 1237 extrn current_dsk:byte 1238 extrn net_delay:word 1239 extrn nul_device:byte 1240 extrn error_code:word 1241 extrn error_class:byte 1242 extrn error_action:byte 1243 extrn error_locus:byte 1244 extrn file_ptr:dword 1245 extrn ldt_ptr:dword 1246 extrn current_device:dword 1247 extrn current_ldt:dword 1248 extrn current_dhndl:dword 1249 extrn current_ddsc:dword 1250 extrn yearsSince1980:byte 1251 extrn days_in_month:byte 1252 extrn name_buf:byte 1253 extrn int21regs_ptr:dword 1254 extrn int24_esbp:dword 1255 extrn int2FNext:dword 1256 extrn fdos_stub:dword 1257 extrn SwStartupInfo:word 1258 extrn err_drv:byte 1259 extrn rwmode:byte 1260 1261 extrn indos_flag:byte, machine_id:byte, internal_data:byte, dmd_upper_root:word 1262 1263 extrn criticalSectionEnable:byte 1264 extrn WindowsHandleCheck:byte 1265 1266 PCMODE_DATA ends 1267 === Switch to base=00C180h -> "GLOBAL_DATA" 1268 section GLOBAL_DATA public align=2 class=DATA 1269 0 000012BE 0500 windowsData dw 5 ; version number ? 0 000012C0 0200 dw $-offset windowsData ; dummy 0 000012C2 0400 dw $-offset windowsData ; dummy 0 000012C4 [0000] dw offset indos_flag 0 000012C6 [0000] dw offset machine_id 0 000012C8 [F6FF] dw offset internal_data-10 0 000012CA [0000] dw offset dmd_upper_root 1277 1278 GLOBAL_DATA ends 1279 1280 end === Trace listing source: drdos/bin/fdos.lst 1 ;title 'F_DOS - DOS file system' 2 ; File : $FDOS.ASM$ 3 ; 4 ; Description : 5 ; 6 ; Original Author : DIGITAL RESEARCH 7 ; 8 ; Last Edited By : $CALDERA$ 9 ; 10 ;-----------------------------------------------------------------------; 11 ; Copyright Work of Caldera, Inc. All Rights Reserved. 12 ; 13 ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, 14 ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. 15 ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES 16 ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF 17 ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO 18 ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE 19 ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE 20 ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, 21 ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, 22 ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, 23 ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF 24 ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT 25 ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND 26 ; CIVIL LIABILITY. 27 ;-----------------------------------------------------------------------; 28 ; 29 ; *** Current Edit History *** 30 ; $Log$ 31 ; FDOS.A86 1.23 93/12/15 03:07:08 32 ; New ddioif entry point so Int 25/26 bypasses address normalisation 33 ; FDOS.A86 1.20 93/09/03 20:25:47 34 ; Add "no critical errors" support (int 21/6C) 35 ; ENDLOG 36 ; 37 ; This is the DOS support function of Concurrent DOS 6.0 38 ; It is called via BDOS function #113, with DS:DX pointing 39 ; to a parameter block. The first word of the parameter 40 ; block is the subfunction number, the remainder are 41 ; parameters or return values, depending on the function. 42 43 ; Date Who Modification 44 ; --------- --- --------------------------------------- 45 ; ?? Feb 86 Initial version 46 ; 7 May 86 speedup MXdisk handling 47 ; ?? Oct 86 used separate file handle & descriptors 48 ; 5 Nov 86 combined with 5.1 BDOS; 49 ; 7 Nov 86 added multiple file search 50 ; 8 Nov 86 added open file checking 51 ; 9 Nov 86 added lock/unlock code 52 ; 14 Nov 86 converted to use new deblocking code 53 ; 17 Nov 86 use RWXIOSIF code, select drive for flush 54 ; 18 Nov 86 first attempt to support character devices 55 ; on WRITE, CLOSE, LSEEK, DATTIM 56 ; 19 Nov 86 some WRITE bugs fixed, MOVE implemented 57 ; RMDIR redone locally (previously BLACK) 58 ; 24 Nov 86 made changes for linked CDOS.CON 59 ; 27 Nov 86 added FCB function entries for BLACK.A86 60 ; 30 Nov 86 added code to support FUNC13 (DRV_RESET) 61 ; 3 Dec 86 added support for CHDIR ("l:=d:\path"); 62 ; 16 Dec 86 update file time stamp on any write 63 ; 23 Jan 86 added support for passwords 64 ; 6 Feb 87 added support for IOCTL status 65 ; 27 Feb 87 updated FCB r/w code to latest spec 66 ; fixed FDOS_CREAT to truncate size to 0L 67 ; 2 Mar 87 Changed FUNC62 to BDOS62 to avoid conflict 68 ; with the linked PCMODE 69 ; 7 Mar 87 changed MF_READ to 0-pad partial FCB records 70 ; 17 Mar 87 fixed ES corruption in FCB_TERM code 71 ; 29 Apr 87 Fixed CHDIR bug which failed to return an error when 72 ; attempting to change to a filename. 73 ; May 87 fixed some FCB bugs 74 ; 19 May 87 changed password mode for FlexOS compatibility 75 ; added IOCTL functions 76 ; 4 Jun 87 zeroed current block on DOS FCB open 77 ; 14 Jun 87 round up writes at end if > 1 sector and rt. fringe 78 ; 19 Jun 87 supported freeing up floating drives 79 ; 28 Jul 87 MX moved into individual funcs for DR NET support 80 ; 29 Jul 87 WRITE_DEV moved to outside MXdisk 81 ; 6 Aug 87 fix some password & partial close problems 82 ; IOCTL(0) bug fixed 83 ; 10 Aug 87 fixed CURDIR path too long problem 84 ; 13 Aug 87 F1',F2' compatibility modes supported 85 ; 20 Aug 87 LOCK_REGION fixed 86 ; 5 Sep 87 lower case DOS FCBs converted to upper case 87 ; 6 Sep 87 free up locked drives on process terminate 88 ; 23 Sep 87 support \path1\path2\devname in DEVICE_ASCIZ: 89 ; 28 Sep 87 use international upper case on ASCIZ paths 90 ; 29 Sep 87 support IOCTL(4), IOCTL(5) 91 ; 7 Oct 87 re-init dir entry on CREAT even if existing file 92 ; return error if CURDIR can't find parent 93 ; 8 Oct 87 don't release handles on disk change 94 ; check OPEN_MAX and LOCK_MAX in SYSDAT 95 ; 13 Oct 87 allow reduced F_OPEN if W,D password not supplied 96 ; 22 Oct 87 support pseudo-networked drives via NET_VEC 97 ; 26 Oct 87 use CBLOCK instead of HDSBLK for CP/M FCB check 98 ; (can now CHDIR between F_OPEN and F_READ) 99 ; 27 Oct 87 reject ".", ".." and " " names on MKDIR, CREAT, MKNEW 100 ; 28 Oct 87 fixed OMODE_COMPAT compatibility checks, 101 ; call SELECT_HANDLE in VFY_DOS_FCB to support 102 ; FCB close after CHDIR 103 ; 29 Oct 87 create label in root only, update VLDCNT in DPH 104 ; delete label in root only, update VLDCNT in DPH 105 ; also update VLDCNT in CREAT and UNLINK 106 ; find labels in root if label only search 107 ; 2 Nov 87 return ED_PATH if level doesn't exist in PATH_PREP 108 ; reject "/path/" as legal ASCIZ specification 109 ; 4 Nov 87 fix release_locks -- didn't work if any locks there 110 ; test F6' on F_LOCK for file size check 111 ; 10 Nov 87 fix F1' compatibility -- test 80h in P_CMOD 112 ; support CREAT on file open in compatibility mode 113 ; by the calling process 114 ; 11 Nov 87 attempt to support multiple compatibility opens 115 ; by several processes in read access mode or 116 ; deny write/read access modes and still have the 117 ; rest of the file sharing working... 118 ; use PCM_ROUT as BIN flag for console handles 119 ; 12 Nov 87 fix file sharing test on MF_OPEN (HM_FCB) 120 ; fix DOS FCB rename of open file (WS 3.x) 121 122 ; 19 Nov 87 Release 6.0/2.0 123 ; --------- --------------- 124 125 ; 21 Nov 87 make NUL device first device in the list 126 ; 1 Dec 87 various network fixes (dup, exec, exit, etc.) 127 ; 2 Dec 87 implement DOS FCB calls across DR Net 128 ; 3 Dec 87 fix CHECK_NOT_OPEN (CALL FILE_UPDATE) (fixes CB86) 129 ; 4 Dec 87 pass drive on network FCB calls 130 ; 7 Dec 87 supported FCB reads/writes across network (via handles) 131 ; 10 Dec 87 fixed month dependant MKDIR bug. 132 ; 11 Dec 87 fixed networked CURDIR bug (for SUBST) 133 ; 5 Jan 88 don't delete labels via FDOS_UNLINK, 134 ; don't access labels via FDOS_CHMOD 135 ; 7 Jan 88 make NUL device first device in chain, in SYSDAT 136 ; 12 Jan 88 setup MAKE_FLAG in FCB_MAKE_TEST 137 ; 15 Jan 88 prevent SUBSTitution of networked drives 138 ; 9 Feb 88 temporarily force door open interrupts 139 ; add GET_FHND, FREE_FHND for dynamic handle create 140 ; 10 Feb 88 update file size in DOS FCB for AutoCAD 141 ; 15 Feb 88 update CUR_IFN in OPEN_HANDLE for MF_OPEN FCB setup 142 ; 25 Feb 88 pass correct unit to driver on generic IOCTL request 143 ; fix removable media check with DOS drivers 144 ; 3 Mar 88 permit multiple compatibility mode opens 145 ; 9 Mar 88 CHDIR ("d:=") always handled locally 146 ; reject CHMOD on character devices 147 ; use LUL_ALLOC for lock list allocation 148 ; 10 Mar 88 Get PSP_XFNMAX before corrupting ES (RMCOBOL) 149 ; 15 Mar 88 split file into three include files 150 ; 28 Jul 88 Support PCMODE Private Device List 151 ; 29 Jul 88 make PRN=LPT1, AUX=COM1 152 ; 27-Feb-89 change PID equate for CDOS, work around RASM bug 153 ; ("PID equ RLR" would cause external ref's to PID!) 154 ; 29-Jun-89 Split off IOCTL into seperate module 155 ; 11-Sep-89 Split off MSNET into seperate module 156 157 group PCMCODE BDOS_CODE 158 group PCMDATA BDOS_DATA PCMODE_DATA 159 160 ASSUME DS:PCMDATA 161 162 [list -] 174 175 FD_EXPAND equ 55h 176 === Switch to base=00C180h -> "PCMODE_DATA" 177 section PCMODE_DATA public align=1 class=DATA 178 179 extrn current_ddsc:dword 180 extrn current_device:dword 181 extrn current_dhndl:dword 182 extrn current_dsk:byte ; default drive 183 extrn current_ifn:word 184 extrn current_ldt:dword 185 extrn current_psp:word ; PSP segment 186 extrn dev_root:dword 187 extrn dma_offset:word ; DTA offset 188 extrn dma_segment:word ; DTA segment 189 extrn file_ptr:dword 190 extrn fdos_stub:dword 191 extrn internal_flag:byte 192 extrn ioexerr:byte 193 extrn join_drv:byte 194 extrn last_drv:byte 195 extrn ldt_ptr:dword ; Pointer to LDT's for the drives 196 extrn lock_tables:dword 197 extrn machine_id:word ; remote process 198 extrn name_buf:byte ; 32 byte name buffer 199 extrn nul_device:dword ; NUL in PCMODE data segment 200 extrn owning_psp:word ; remote PSP segment 201 extrn phys_drv:byte 202 extrn remote_call:word ; remote machine flag 203 extrn share_stub:dword 204 extrn srch_buf:byte 205 extrn pri_pathname:byte 206 extrn sec_pathname:byte 207 extrn temp_ldt:byte 208 extrn unlock_tables:dword 209 extrn WindowsHandleCheck:byte 210 extrn net_delay:word 211 212 %ifdef KANJI 213 extrn DBCS_tbl:word ; Double Byte Character Table 214 %endif 215 216 PCMODE_DATA ends 217 === Switch to base=00C180h -> "BDOS_DATA" 218 section BDOS_DATA public align=2 class=DATA 219 220 extrn lfnpathflag:byte 221 222 extrn adrive:byte 223 extrn cur_dma:word 224 extrn cur_dma_seg:word 225 extrn mult_sec:word 226 extrn rwmode:byte 227 extrn valid_flg:byte 228 extrn dosfat:word 229 0 000018D4 00000000 chdir_cl dw 0,0 0 000018D8 00000000 chkcds_cl dw 0,0 232 233 NO_CRIT_ERRORS equ 01000000b ; critical error shouldn't be generated 234 ; warning - must match PCMODE.EQU 235 236 extrn fdrwflg:byte 237 extrn chdblk:word 238 extrn dcnt:word 239 extrn dirp:word 240 extrn dirperclu:word 241 extrn finddfcb_mask:word 242 extrn hdsaddr:word 243 extrn intl_xlat:dword 244 extrn lastcl:word 245 extrn blastcl:word 246 extrn logical_drv:byte 247 extrn pblock:dword 248 extrn physical_drv:byte 249 extrn req_hdr:byte 250 251 252 extrn yearsSince1980:word 253 extrn month:byte 254 extrn dayOfMonth:byte 255 extrn hour:byte 256 extrn minute:byte 257 extrn second:byte 258 0 000018DC 0000 orig_drive dw 0 0 000018DE 0000 path_drive dw 0 261 262 263 Public fdos_hds_blk, fdos_hds_root, fdos_hds_drv 264 265 fdos_hds label word ; temporary HDS that we make up 0 000018E0 00000000 fdos_hds_blk dw 0,0 0 000018E4 00000000 fdos_hds_root dw 0,0 0 000018E8 00 fdos_hds_drv db 0 269 270 HDS_LEN equ offset $ - offset fdos_hds 271 272 saved_hds label word ; saved HDS on F_DOS rename 0 000018E9 00000000 saved_hds_blk dw 0,0 0 000018ED 00000000 saved_hds_root dw 0,0 0 000018F1 00 saved_hds_drv db 0 276 0 000018F2 0000 saved_dcnt dw 0 ; saved DCNT on F_DOS rename 278 0 000018F4 00 dta_ofl db 0 ; non-zero if read/write > DTA size 280 0 000018F5 0000 extflg dw 0 ; DOS FCB was extended FCB 282 0 000018F7 00000000 blk dw 0,0 ; temp variable for cluster # 284 0 000018FB 00 attributes db 0 ;fcb interface attributes hold byte 286 287 public info_fcb 0 000018FC 000000000000000000 info_fcb db 1+8+3 dup (0) ;local user FCB drive+name+ext 0 00001905 000000 289 0 00001908 000000000000000000 save_area db 32 dup (0) ;save area for dirbuf during rename and 0 00001911 000000000000000000 0 0000191A 000000000000000000 0 00001923 0000000000 291 ;info_fcb during create(mustbe_nolbl) 292 ;parental name during chdir 293 294 ; local variables for fdos operations 295 0 00001928 0000 sp_save dw 0 297 0 0000192A 0000 fdos_addr dw 0 ; address of F_DOS function 299 300 Public fdos_info, fdos_pb, fdos_ret 301 0 0000192C 000000000000 fdos_info dw 3 dup (0) ; off, seg, size of parameter block 0 00001932 000000000000000000 fdos_pb dw 7 dup (0) ; copy of parameter block 0 0000193B 0000000000 0 00001940 0000 fdos_ret dw 0 ; return value for function 305 306 %ifdef PASSWORD 307 ; Password support uses the following data stuctures: 308 ; 309 ; The global_password field is set by an IOCTL call and remains constant. 310 ; 311 ; When a password is encountered during parsing a path the ASCII form is 312 ; copied into the password_buffer. It is then encrypted and stored in the 313 ; local_password field. If a password protected file is encountered then 314 ; it's encrypted password is compared with both the global and local passwords. 315 ; 316 ; During a file/directory create the local_password field is examnined. If 317 ; non-zero then this encrypted password is applied to the file, which is given 318 ; full protection. 319 ; 320 Public global_password 0 00001942 0000 global_password dw 0 0 00001944 0000 local_password dw 0 0 00001946 0000000000000000 password_buffer db 8 dup (0) 324 325 %endif 326 327 BDOS_DATA ends 328 === Switch to base=000000h -> "BDOS_CODE" 329 section BDOS_CODE public align=1 class=CODE 330 331 332 extrn pcmode_dseg:word ; Pointer to System Data Page 333 334 extrn get_ldt:near 335 extrn get_ldt_raw:near 336 extrn islocal:near ; redirector support 337 extrn redir_asciiz_offer:near 338 extrn redir_asciiz_dev_offer:near 339 extrn redir_asciiz_file_offer:near 340 extrn redir_drv_offer:near 341 extrn redir_dhndl_offer:near 342 extrn redir_move_offer:near 343 extrn redir_snext_offer:near 344 345 extrn alloc_cluster:NEAR 346 extrn allocdir:NEAR ; will extend subdirectory if full 347 extrn buffers_check:near 348 extrn discard_all:near 349 extrn close_dev:near ; close character device handle 350 extrn delfat:NEAR 351 extrn fdosrw:near ; read/write from/to disk file 352 extrn finddfcb:NEAR ; find next matching directory entry 353 extrn finddfcbf:NEAR ; find first matching directory entry 354 extrn first_dev:near ; find first matching character device 355 extrn fill_dirbuf:near 356 extrn flush_dirbuf:near 357 extrn flush_drive:near 358 extrn get_ddsc:near 359 extrn getdir:NEAR 360 extrn getnblk:NEAR 361 extrn hshdscrd:near ; discard hashing for drive AL 362 363 extrn mark_ldt_unsure:near 364 extrn redir_build_path:near ; build ASCII path 365 366 extrn open_dev:near ; open character device handle 367 extrn dup_dev:near ; call device driver on handle dup 368 extrn read_dev:near ; read from character device 369 extrn ReadTimeAndDate:near ; read date/time from CLOCK driver 370 extrn blockif:near 371 extrn ddioif:near 372 extrn select_logical_drv:near 373 extrn select_physical_drv:near 374 extrn setenddir:NEAR 375 extrn update_dat:NEAR ; flush dirty data buffers 376 extrn update_ddsc_free:NEAR ; count free blocks on drive 377 extrn update_dir:NEAR ; flush modified directory buffer 378 extrn update_fat:NEAR 379 extrn write_dev:near ; write to character device 380 extrn zeroblk:near ; fill cluster with 0's 381 extrn is_lfn:near ; check if long filename entry 382 extrn del_lfn:near ; delete long filenames 383 384 public bpb2ddsc ; build DDSC from a BPB 385 Public check_slash 386 public dbcs_lead 387 public discard_files ; discard open files (unconditional) 388 public fdos_ED_DRIVE ; Return ED_DRIVE error 389 public fdos_ED_FUNCTION ; Return ED_FUNCTION error 390 public find_dhndl 391 public find_xfn 392 public get_pb2_drive 393 public release_handle ; release file handle 394 public toupper ; upper case a character 395 Public unparse 396 public update_dir_fat ; flush DIR then FAT to disk 397 public get_path_drive ; get drive number for given path 398 public path_prep 399 public check_no_wild 400 401 public fdos_getdpb ; 0-disk information 402 public fdos_mkdir ; 1-make directory 403 public fdos_rmdir ; 2-remove directory 404 public fdos_chdir ; 3-change directory 405 public fdos_creat ; 4-create file 406 public fdos_open ; 5-open file 407 public fdos_close ; 6-close file 408 public fdos_read ; 7-read from file 409 public fdos_write ; 8-write to file 410 public fdos_unlink ; 9-delete file 411 public fdos_lseek ; 10-set file pointer 412 public fdos_chmod ; 11-get/set file attributes 413 public fdos_curdir ; 12-get current directory 414 public fdos_first ; 13-find first matching file 415 public fdos_next ; 14-find next matching file 416 public fdos_move ; 15-rename file 417 public fdos_dattim ; 16-get/set file name 418 public fdos_flush ; 17-flush buffers 419 public fdos_mknew ; 18-make new file 420 public fdos_lock ; 19-lock/unlock block 421 public fdos_dup ; 20-duplicate handle 422 public fdos_fdup ; 21-force duplicate handle 423 extrn fdos_fcb:near ; 22-FCB emulation 424 public fdos_exec ; 23-create child PSP 425 extrn fdos_exit:near ; 24-FCB close for PSP 426 public fdos_ddio ; 25-direct disk access 427 extrn fdos_ioctl:near ; 26-IOCTL emulation 428 public fdos_commit ; 27-commit file 429 public fdos_expand ; 28-expand file name 430 public fdos_mkddsc ; 29-build DDSC from BPB 431 public fdos_select ; 30-select drive 432 433 %ifdef JOIN 434 Public check_join 435 Public mv_join_root 436 %endif 437 438 BDOS_CODE ends 439 440 ;=== Push trace listing source: drdos/funcs.nas 441 %include "funcs.nas" 1 <1> ; File : $FUNCS.FDO$ 2 <1> ; 3 <1> ; Description : 4 <1> ; 5 <1> ; Original Author : DIGITAL RESEARCH 6 <1> ; 7 <1> ; Last Edited By : $CALDERA$ 8 <1> ; 9 <1> ;-----------------------------------------------------------------------; 10 <1> ; Copyright Work of Caldera, Inc. All Rights Reserved. 11 <1> ; 12 <1> ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, 13 <1> ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. 14 <1> ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES 15 <1> ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF 16 <1> ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO 17 <1> ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE 18 <1> ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE 19 <1> ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, 20 <1> ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, 21 <1> ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, 22 <1> ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF 23 <1> ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT 24 <1> ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND 25 <1> ; CIVIL LIABILITY. 26 <1> ;-----------------------------------------------------------------------; 27 <1> ; 28 <1> ; *** Current Edit History *** 29 <1> ; *** End of Current Edit History ***; 30 <1> ; $Log$; 31 <1> ; ENDLOG 32 <1> ; General function include module for FDOS.A86 33 <1> === Switch to base=000000h -> "BDOS_CODE" 34 <1> section BDOS_CODE public align=1 class=CODE 34 ****************** <1> warning: segment attributes specified on redeclaration of segment: ignoring [-w+other] 35 <1> extrn mul32:near 36 <1> extrn output_hex:near 37 <1> 38 <1> public fdos_entry 39 <1> 40 <1> ;========== 41 <1> fdos_entry: ; FDOS module entry point 42 <1> ;========== 43 <1> ; On Entry: 44 <1> ; DS:DX -> parameter block 45 <1> ; On exit: 46 <1> ; AX = BX = return code 47 <1> ; (DS/ES corrupted) 48 <1> ; entry: DS:DX = argument 49 <1> ; 50 <1> ; exit: AX,BX = return code 51 <1> 0 00006D46 89D6 mov si,dx 0 00006D48 AD lodsw ; AX = FDOS number 0 00006D49 83E839 sub ax,39h ; base it at zero 0 00006D4C 721B jc fd_error ; stop if too low 0 00006D4E 83F820 cmp ax,FDOS_MAX ; check if function in range 0 00006D51 7316 jae fd_error ; yes, continue 58 <1> 0 00006D53 1E push ds ; save parameter segment 0 00006D54 52 push dx ; save parameter offset 0 00006D55 50 push ax ; save sub-function 0 00006D56 89E5 mov bp,sp ; SS:BP -> working variables 0 00006D58 89C3 mov bx,ax 0 00006D5A 01C3 add bx,ax 0 00006D5C 01C3 add bx,ax 0 00006D5E 2EFF97[2900] call [cs:fdos_tbl + bx] 0 00006D63 83C406 add sp,3*2 ; clean up stack 0 00006D66 89D8 mov ax,bx 0 00006D68 C3 ret 70 <1> 71 <1> fd_error: 0 00006D69 B8FFFF mov ax,ED_FUNCTION ; return "invalid function" 0 00006D6C 89C3 mov bx,ax 0 00006D6E C3 ret 75 <1> 76 <1> 0 00006D6F [1E01] fdos_tbl dw fdos_mkdir ; 39-make directory 0 00006D71 02 db 2 0 00006D72 [8D01] dw fdos_rmdir ; 3A-remove directory 0 00006D74 02 db 2 0 00006D75 [D301] dw fdos_chdir ; 3B-change directory 0 00006D77 02 db 2 0 00006D78 [4403] dw fdos_creat ; 3C-create file 0 00006D7A 04 db 4 0 00006D7B [D503] dw fdos_open ; 3D-open file 0 00006D7D 04 db 4 0 00006D7E [4C04] dw fdos_close ; 3E-close file 0 00006D80 01 db 1 0 00006D81 [7F04] dw fdos_read ; 3F-read from file 0 00006D83 04 db 4 0 00006D84 [E804] dw fdos_write ; 40-write to file 0 00006D86 04 db 4 0 00006D87 [2105] dw fdos_unlink ; 41-delete file 0 00006D89 04 db 4 0 00006D8A [A105] dw fdos_lseek ; 42-set file pointer 0 00006D8C 04 db 4 0 00006D8D [6106] dw fdos_chmod ; 43-get/set file attributes 0 00006D8F 06 db 6 0 00006D90 [0000] dw fdos_ioctl ; 44-IOCTL emulation 0 00006D92 03 db 3 0 00006D93 [BF07] dw fdos_dup ; 45-duplicate handle 0 00006D95 02 db 2 0 00006D96 [CE07] dw fdos_fdup ; 46-force duplicate handle 0 00006D98 02 db 2 0 00006D99 [0908] dw fdos_curdir ; 47-get current directory 0 00006D9B 03 db 3 0 00006D9C [5708] dw fdos_getdpb ;*48*disk information 0 00006D9E 04 db 4 0 00006D9F [8D08] dw fdos_flush ;*49*flush buffers 0 00006DA1 00 db 0 0 00006DA2 [BF08] dw fdos_select ;*4A*drive select 0 00006DA4 01 db 1 0 00006DA5 [F208] dw fdos_exec ;*4B*create child PSP 0 00006DA7 01 db 1 0 00006DA8 [0000] dw fdos_exit ;*4C*close child PSP 0 00006DAA 00 db 0 0 00006DAB [0000] dw fdos_fcb ;*4D*generic FCB call 0 00006DAD 05 db 5 0 00006DAE [5209] dw fdos_first ; 4E-find first matching file 0 00006DB0 04 db 4 0 00006DB1 [7B09] dw fdos_next ; 4F-find next matching file 0 00006DB3 00 db 0 0 00006DB4 [760A] dw fdos_commit ;*50*commit file 0 00006DB6 01 db 1 0 00006DB7 [090B] dw fdos_mknew ;*51*make new file 0 00006DB9 04 db 4 0 00006DBA [2D0B] dw fdos_lock ;*52*lock/unlock block 0 00006DBC 06 db 6 0 00006DBD [570B] dw fdos_mkddsc ; 53 build DDSC from BPB 0 00006DBF 04 db 4 0 00006DC0 [E10C] dw fdos_ddio ;*54*Int 25/26 emulation 0 00006DC2 06 db 6 0 00006DC3 [510D] dw fdos_expand ;*55*expand file name 0 00006DC5 06 db 6 0 00006DC6 [4B0E] dw fdos_move ; 56-rename file 0 00006DC8 06 db 6 0 00006DC9 [C50F] dw fdos_dattim ; 57-get/set file name 0 00006DCB 04 db 4 0 00006DCC [0910] dw fdos_reopen_fcb ; 58-FCB reopen support function 0 00006DCE 05 db 5 141 <1> 142 <1> FDOS_MAX equ (offset $ - offset fdos_tbl) / 3 143 <1> 144 <1> Public local_disk 145 <1> 146 <1> local_disk: ; continue execution within MXdisk semaphore 147 <1> ;---------- 148 <1> ; This function will make local copies of the parameters 149 <1> ; and continue 150 <1> 0 00006DCF 36FF1E[0000] call far [ss:lock_tables] 0 00006DD4 8F06[5600] pop word [fdos_addr] ; return address 0 00006DD8 83C404 add sp,2*2 ; discard return from call fdos_tbl[bx] 154 <1> ; and function # 0 00006DDB 5E pop si ; get parameter offset 0 00006DDC 58 pop ax ; get parameter segment 0 00006DDD 8926[5400] mov [sp_save],sp ; save for re-entry/errors 0 00006DE1 8ED8 mov ds,ax ; DS:SI -> paremeter block 159 <1> fdos_reenter: 0 00006DE3 16 push ss 0 00006DE4 07 pop es ; ES = local data segment 0 00006DE5 BF[5E00] mov di,offset fdos_pb ; ES:DI -> local parameter block copy 0 00006DE8 AD lodsw 0 00006DE9 AB stosw ; load subfunction number 0 00006DEA 268936[5800] mov [es:fdos_info],si ; save it for BDOS return 0 00006DEF 268C1E[5A00] mov [es:fdos_info+2],ds ; save parameter segment for return 0 00006DF4 89C3 mov bx,ax 0 00006DF6 01C3 add bx,ax 0 00006DF8 01C3 add bx,ax ; BX = function # * 3 0 00006DFA 2E8A8F[80FF] mov cl,byte ptr [cs:bx+fdos_tbl-(39h*(2+1))+2] 0 00006DFF B500 mov ch,0 172 <1> ; get table of # of parameters 0 00006E01 26890E[5C00] mov [es:fdos_info+2*2],cx ; save the parameter count 0 00006E06 F3A5 rep movsw ; copy parameter block 0 00006E08 06 push es 0 00006E09 1F pop ds ; DS = SYSDAT 0 00006E0A C606[0000]FF mov byte [ioexerr],0FFh ; assume default error code 0 00006E0F C606[0000]00 mov byte [rwmode],0 179 <1> 0 00006E14 C706[0000]0008 mov word [finddfcb_mask],DA_VOLUME*256 181 <1> 0 00006E1A 31C0 xor ax,ax 0 00006E1C A3[6C00] mov [fdos_ret],ax ; assume success unless proven otherwise 0 00006E1F FF16[5600] call near [fdos_addr] ; call code following "call local_disk" 0 00006E23 A1[6C00] mov ax,[fdos_ret] ; get return code, fall thru to exit 186 <1> 187 <1> Public fdos_error 188 <1> 189 <1> fdos_error: 190 <1> ;---------- 191 <1> ; AX = return code 0 00006E26 8B26[5400] mov sp,[sp_save] ; stack to entry value (for errors) 0 00006E2A BE[6000] mov si,offset fdos_pb+2 ; get local copy 0 00006E2D C43E[5800] les di,[fdos_info] ; get parameter block address 0 00006E31 8B0E[5C00] mov cx,[fdos_info+2*2] ; get parameter block size 0 00006E35 F3A5 rep movsw ; copy return values 0 00006E37 89C3 mov bx,ax 0 00006E39 36FF1E[0000] call far [ss:unlock_tables] 0 00006E3E C3 ret ; return to BDOS, which copies BX to AX 200 <1> 201 <1> Public fdos_restart 202 <1> 203 <1> fdos_restart: ; we want to restart the function after an error 204 <1> ;------------ ; we already have MXdisk 205 <1> ; 0 00006E3F 8B26[5400] mov sp,[sp_save] ; break out from low levels 0 00006E43 C536[5800] lds si,[fdos_info] 0 00006E47 4E dec si 0 00006E48 4E dec si ; DS:SI -> parameter block 0 00006E49 EB98 jmp fdos_reenter ; try from scratch 211 <1> 212 <1> fdos_ED_ROOM: 213 <1> ;----------- 0 00006E4B B8EEFF mov ax,ED_ROOM ; no more files 0 00006E4E EBD6 jmp fdos_error 216 <1> 217 <1> fdos_ED_DRIVE: 218 <1> ;----------- 0 00006E50 B8F1FF mov ax,ED_DRIVE ; bad drive 0 00006E53 EBD1 jmp fdos_error 221 <1> 222 <1> fdos_ED_PATH: 0 00006E55 B8FDFF mov ax,ED_PATH ; invalid path or drive 0 00006E58 EBCC jmp fdos_error 225 <1> 226 <1> fdos_ED_PROTECT: 0 00006E5A B8EDFF mov ax,ED_PROTECT ; write protect error 0 00006E5D EBC7 jmp fdos_error 229 <1> 230 <1> Public fdos_ED_ACCESS 231 <1> 232 <1> fdos_ED_ACCESS: 0 00006E5F B8FBFF mov ax,ED_ACCESS ; access denied error 0 00006E62 EBC2 jmp fdos_error 235 <1> 236 <1> ; MAKE DIRECTORY (MKDIR) 237 <1> 238 <1> ; +----+----+----+----+----+----+ 239 <1> ; | 39 | name | 240 <1> ; +----+----+----+----+----+----+ 241 <1> 242 <1> ; entry: 243 <1> ; ------ 244 <1> ; name: segmented address of ASCIIZ name 245 <1> 246 <1> ; exit: 247 <1> ; ----- 248 <1> ; AX: 0000 or error code ( < 0) 249 <1> 250 <1> fdos_mkdir: 251 <1> ;---------- 0 00006E64 E8[0000] call redir_asciiz_offer 0 00006E67 E865FF call local_disk ; get MXdisk, switch stack 0 00006E6A E83815 call path_prep_chk ; parse path, walk down the tree 0 00006E6D E8[0000] call finddfcbf ; find matching FCB 0 00006E70 7557 jnz mkdir_access ; file/dir exists, "access denied" 0 00006E72 E8[0000] call allocdir ; allocate a directory entry 258 <1> 0 00006E75 50 push ax ; save pointer to directory entry 0 00006E76 8D36[2900] lea si,[info_fcb+1] ; SI -> file name 0 00006E7A 97 xchg ax,di ; DI -> DNAME 0 00006E7B B90B00 mov cx,11 0 00006E7E F3A4 rep movsb ; copy file name into directory buffer 264 <1> ; lea di,DATTS[si] 0 00006E80 B010 mov al,DA_DIR 0 00006E82 AA stosb ; mark it as a directory 0 00006E83 31C0 xor ax,ax 0 00006E85 B91400 mov cx,(32-12) 0 00006E88 F3AA rep stosb ; zero remainder of new FCB 0 00006E8A 5E pop si ; SI -> directory 271 <1> 0 00006E8B E8B31B call stamp_dir_entry ; set time and date in FCB 0 00006E8E 31C0 xor ax,ax 0 00006E90 31D2 xor dx,dx 0 00006E92 E8[0000] call alloc_cluster ; Allocate a block 0 00006E95 7228 jc mkdir_err ; Report Error(no room on disk) 0 00006E97 8B36[0000] mov si,[dirp] 0 00006E9B 89441A mov [DBLOCK1 + si],ax ; Initialize 1st block of fcb 0 00006E9E 833E[0000]00 cmp word [dosfat],FAT32 ; 32-bit file system? 0 00006EA3 7503 jne fdos_mkdir10 ; no, then do not use high word of cluster 0 00006EA5 895414 mov [DBLOCK1H + si],dx 282 <1> fdos_mkdir10: 0 00006EA8 52 push dx 0 00006EA9 50 push ax ; save block 0 00006EAA E8[0000] call update_fat ; Write the fat to disk 0 00006EAD E8[0000] call update_dir ; Write the directory to disk 0 00006EB0 58 pop ax ; now initialise the sub-directory 0 00006EB1 5A pop dx 0 00006EB2 E89F12 call mkdir_init ; '.' and '..' entries 0 00006EB5 E8[0000] call update_dir ; update directory entry 0 00006EB8 B80500 mov ax,5 ; return a magic value for some 0 00006EBB A3[6C00] mov [fdos_ret],ax ; PD expansion program 0 00006EBE C3 ret 294 <1> 295 <1> mkdir_err: 296 <1> ;--------- 0 00006EBF 8B1E[0000] mov bx,[dirp] ; can't make dir, no data space 0 00006EC3 C607E5 mov byte [DNAME + bx],0E5h ; so release our directory entry 0 00006EC6 E8[0000] call update_dir ; release this entry 300 <1> mkdir_access: 0 00006EC9 EB94 jmp fdos_ED_ACCESS ; return "access denied" error 302 <1> 303 <1> chk_no_dot: ; reject "." and ".." names 0 00006ECB 803E[2900]2E cmp byte [info_fcb+1],'.' 0 00006ED0 74F7 je mkdir_access 0 00006ED2 C3 ret 307 <1> 308 <1> ; REMOVE DIRECTORY (RMDIR) 309 <1> 310 <1> ; +----+----+----+----+----+----+ 311 <1> ; | 3A | name | 312 <1> ; +----+----+----+----+----+----+ 313 <1> 314 <1> ; entry: 315 <1> ; ------ 316 <1> ; name: segmented address of ASCIIZ name 317 <1> 318 <1> ; exit: 319 <1> ; ----- 320 <1> ; AX: 0000 or error code ( < 0) 321 <1> 322 <1> fdos_rmdir: 323 <1> ;---------- 0 00006ED3 E8[0000] call redir_asciiz_offer 0 00006ED6 E8F6FE call local_disk ; get MXdisk, switch stack 0 00006ED9 E8C914 call path_prep_chk ; parse path to bottom level 0 00006EDC E8[0000] call finddfcbf ; try to locate directory entry 0 00006EDF 7423 jz fdos_rmdir20 ; skip if we can't find it 0 00006EE1 F6470B10 test byte [DATTS + bx],DA_DIR ; check directory attribute 0 00006EE5 7420 jz fdos_rmdir30 ; O.K. if a directory 0 00006EE7 E82913 call chkcds ; make sure no-where current 0 00006EEA 731E jnc fdos_rmdir40 0 00006EEC E8F90F call path_prep ; redo as rmdir_ok may destroy info 0 00006EEF E8[0000] call finddfcbf ; find the entry again 0 00006EF2 E8AD12 call rmdir_ok ; make sure not in use 0 00006EF5 E8[0000] call finddfcbf ; find the entry again 337 <1> %ifdef PASSWORD 0 00006EF8 E8E41B call check_pwd_any 339 <1> %endif 340 <1> kill_entry: 0 00006EFB E82816 call kill_file ; actually delete entry 342 <1> update_dir_fat: 0 00006EFE E8[0000] call update_dir ; update directory entry 0 00006F01 E9[0000] jmp update_fat ; update file allocation table 345 <1> 346 <1> fdos_rmdir20: 0 00006F04 E94EFF jmp fdos_ED_PATH ; "invalid path" 348 <1> 349 <1> fdos_rmdir30: 0 00006F07 E955FF jmp fdos_ED_ACCESS ; "access denied" 351 <1> 352 <1> fdos_rmdir40: 0 00006F0A B8F0FF mov ax,ED_DIR 0 00006F0D E916FF jmp fdos_error 355 <1> 356 <1> ; CHANGE DIRECTORY (CHDIR) 357 <1> 358 <1> ; +----+----+----+----+----+----+ 359 <1> ; | 3B | name | 360 <1> ; +----+----+----+----+----+----+ 361 <1> 362 <1> ; entry: 363 <1> ; ------ 364 <1> ; name: segmented address of ASCIIZ name 365 <1> 366 <1> ; exit: 367 <1> ; ----- 368 <1> ; AX: 0000 or error code ( < 0) 369 <1> 370 <1> 371 <1> chdir_ED_PATH: 0 00006F10 E942FF jmp fdos_ED_PATH ; all logical errors give "no path" 373 <1> 374 <1> chdir_ED_DRIVE: 0 00006F13 B8F1FF mov ax,ED_DRIVE ; bad drive error message 376 <1> chdir_err: 0 00006F16 E90DFF jmp fdos_error 378 <1> 379 <1> fdos_chdir: 380 <1> ;---------- 0 00006F19 E8[0000] call redir_asciiz_offer 0 00006F1C E8B0FE call local_disk ; get MXdisk, switch stack 383 <1> fdos_move_chdir: 384 <1> ;--------------- 0 00006F1F C706[0800]FFFF mov word [orig_drive],0FFFFh ; set drive to invalid 0 00006F25 C43E[6000] les di,[fdos_pb+2] ; get string address 0 00006F29 E81311 call get_path_drive ; from asciiz or default 0 00006F2C 72E5 jc chdir_ED_DRIVE ; continue if drive A: - Z: 0 00006F2E E8[0000] call islocal ; reject networked drives 0 00006F31 72E0 jc chdir_ED_DRIVE ; as bad drives 0 00006F33 E8C70F call path_prep_cont ; continue if drive legal 0 00006F36 72DE jc chdir_err ; return error to application 0 00006F38 E8D111 call chk_no_dev ; no devices allowed 0 00006F3B E87014 call chk_no_wild ; no wild cards allowed here 0 00006F3E 833E[0800]FF cmp word [orig_drive],0FFFFh ; check if assign to specified drive 0 00006F43 7506 jne chdir10 ; skip drive specified 0 00006F45 A1[0A00] mov ax,[path_drive] ; else same as path drive 0 00006F48 A3[0800] mov [orig_drive],ax 399 <1> chdir10: 400 <1> %ifdef JOIN 0 00006F4B E81C1A call offer_join ; are we opening a JOIN'd drive ? 0 00006F4E 7318 jnc chdir30 ; if so move to it and skip open_dir 403 <1> %endif 0 00006F50 E87E14 call chk_for_root ; check if we are in the root 0 00006F53 7413 je chdir30 ; if so, just skip the open_dir 0 00006F55 E8[0000] call finddfcbf ; try to locate directory entry 0 00006F58 74B6 jz chdir_ED_PATH ; skip if no valid directory 0 00006F5A F6470B10 test byte [DATTS + bx],DA_DIR ; check directory attribute 0 00006F5E 74B0 jz chdir_ED_PATH ; return if not a directory 410 <1> %ifdef PASSWORD 0 00006F60 E87C1B call check_pwd_any ; check if PW prot'd & wrong PW 412 <1> %endif 0 00006F63 E81213 call open_dir ; else open last directory 0 00006F66 72A8 jc chdir_ED_PATH ; return an error if we can't 415 <1> chdir30: 0 00006F68 A1[0800] mov ax,[orig_drive] ; get logical drive 0 00006F6B E8[0000] call get_ldt ; ES:BX -> LDT_ 0 00006F6E 72DB jc chdir10 ; no LDT_, must be init time... 0 00006F70 268B7743 mov si,[es:LDT_FLAGS + bx] ; normally we inherit parents 0 00006F74 268B4F4F mov cx,[es:LDT_ROOTLEN + bx] ; root block and drive 0 00006F78 268B574B mov dx,[es:LDT_ROOT + bx] ; if it's a "SUBST I: C:\PATH" form 0 00006F7C 8916[0000] mov [chdir_cl],dx 0 00006F80 268B5753 mov dx,[es:LDT_ROOTH + bx] 0 00006F84 8916[0200] mov [chdir_cl+2],dx 0 00006F88 268B17 mov dx,word ptr [es:LDT_NAME + bx] 426 <1> ; mov bx,es:LDT_ROOT[bx] ; if it's a "SUBST I: C:\PATH" form 0 00006F8B 3B06[0A00] cmp ax,[path_drive] ; we pick up new root and drive 0 00006F8F 7420 je chdir50 ; like this 0 00006F91 A1[0A00] mov ax,[path_drive] ; ASCII drive from path drive 0 00006F94 BA413A mov dx,'A'+256*':' ; make it into ASCII "C:" 0 00006F97 01C2 add dx,ax ; in case LDT does not exist 0 00006F99 E8[0000] call get_ldt ; get LDT_ in case it's subst'd 0 00006F9C 7203 jc chdir40 0 00006F9E 268B17 mov dx,word ptr [es:LDT_NAME + bx] 435 <1> chdir40: 0 00006FA1 8B1E[0C00] mov bx,[fdos_hds_blk] ; root block from fdos_hds 0 00006FA5 891E[0000] mov [chdir_cl],bx 0 00006FA9 8B1E[0E00] mov bx,[fdos_hds_blk+2] 0 00006FAD 891E[0200] mov [chdir_cl+2],bx 440 <1> chdir50: 0 00006FB1 BF[0000] mov di,offset pri_pathname ; build new LDT_ here 0 00006FB4 81CE0040 or si,LFLG_PHYSICAL ; drive is always physical 0 00006FB8 897543 mov [LDT_FLAGS + di],si 0 00006FBB 894D4F mov [LDT_ROOTLEN + di],cx ; inherit rootlen from parent 0 00006FBE 8B1E[0000] mov bx,[chdir_cl] 0 00006FC2 895D4B mov [LDT_ROOT + di],bx ; root as above 0 00006FC5 8B1E[0200] mov bx,[chdir_cl+2] 0 00006FC9 895D53 mov [LDT_ROOTH + di],bx 0 00006FCC A1[0C00] mov ax,[fdos_hds_blk] ; current block from HDS 0 00006FCF 894549 mov [LDT_BLK + di],ax 0 00006FD2 A1[0E00] mov ax,[fdos_hds_blk+2] 0 00006FD5 894551 mov [LDT_BLKH + di],ax 0 00006FD8 A0[1400] mov al,[fdos_hds_drv] ; current drive we from HDS 0 00006FDB 88454D mov [LDT_DRV + di],al 0 00006FDE A1[0000] mov ax,word ptr [current_ddsc] 0 00006FE1 894545 mov word ptr [LDT_PDT + di],ax 0 00006FE4 A1[0200] mov ax,word ptr [current_ddsc+2] 0 00006FE7 894547 mov word ptr [di+LDT_PDT+2],ax 0 00006FEA 16 push ss 0 00006FEB 07 pop es ; now build ASCII path 461 <1> ; lea di,LDT_NAME[di] ; ES:DI -> name 0 00006FEC 92 xchg ax,dx 0 00006FED AB stosw ; plant 'A:' 0 00006FEE B85C00 mov ax,'\' 0 00006FF1 AB stosw ; make that 'A:\',0 0 00006FF2 4F dec di ; point at NUL 0 00006FF3 C706[1000]0000 mov word [fdos_hds_root],0 ; we want to go back to root 0 00006FF9 C706[1200]0000 mov word [fdos_hds_root+2],0 0 00006FFF 893E[6400] mov [fdos_pb+6],di ; rebuild into LDT_ at the address 0 00007003 8C06[6600] mov [fdos_pb+8],es 0 00007007 1E push ds 0 00007008 07 pop es 473 <1> chdir60: 0 00007009 E8C212 call hdsblk ; get current block 475 <1> %ifdef JOIN 0 0000700C 751F jnz chdir65 ; if not at root unparse 0 0000700E E80219 call check_join ; check if drive is joined to another 0 00007011 743F jz chdir80 ; at root, unJOIN'd, so exit 479 <1> ; we are at the root of this drive 0 00007013 8606[1400] xchg al,[fdos_hds_drv] ; update HDS drive so we can force 0 00007017 06 push es ; an exit next time round 0 00007018 E8[0000] call get_ldt ; now copy the JOIN'd name 0 0000701B 1E push ds 0 0000701C 06 push es 0 0000701D 1F pop ds 0 0000701E 07 pop es 0 0000701F 8D7703 lea si,[LDT_NAME+3 + bx] ; point to my JOIN data 0 00007022 BF[3400] mov di,offset save_area 0 00007025 E8E418 call copy_asciiz 0 00007028 06 push es 0 00007029 1F pop ds 0 0000702A 07 pop es 0 0000702B EB03 jmp chdir70 ; copy this into place 494 <1> chdir65: 495 <1> %else 496 <1> jz chdir80 ; if at root, we're done 497 <1> %endif 0 0000702D E8AC12 call parent2save_area ; parental name written in save_area 499 <1> chdir70: 0 00007030 4F dec di ; DI -> '\0' at end 0 00007031 B05C mov al,'\' 0 00007033 AA stosb ; add a trailing backslash 0 00007034 81EF[3500] sub di,offset save_area+1 0 00007038 89FA mov dx,di ; DX = length of name 505 <1> 0 0000703A 06 push es ; insert name into user buffer 0 0000703B C43E[6400] les di,[fdos_pb+6] 0 0000703F B000 mov al,0 0 00007041 AE scasb ; check if first directory 0 00007042 7401 je chdir75 ; if not 1st in path 0 00007044 42 inc dx ; we need space for '\' 512 <1> chdir75: 0 00007045 4F dec di ; adjust for scan 0 00007046 E8D912 call mkspace_parent ; move ES:DI up by DX bytes 0 00007049 8B3E[6400] mov di,[fdos_pb+6] ; ES:DI -> user buffer 0 0000704D F3A4 rep movsb ; copy directory into user buffer 0 0000704F 07 pop es ; ES = local segment again 0 00007050 EBB7 jmp chdir60 ; try again til root 519 <1> 520 <1> chdir80: ; arrive here when root reached 0 00007052 A1[0800] mov ax,[orig_drive] ; get logical drive 0 00007055 E8[0000] call get_ldt ; ES:BX -> LDT_ 0 00007058 722F jc chdir85 ; no LDT_, what happended ? 0 0000705A 1E push ds 0 0000705B 89DF mov di,bx ; ES:DI -> destination LDT_ 0 0000705D 16 push ss 0 0000705E 1F pop ds 0 0000705F BE[0000] mov si,offset pri_pathname ; DS:SI -> new LDT_ we just built 0 00007062 B95800 mov cx,LDT_LEN 0 00007065 F3A4 rep movsb ; copy the new LDT_ into place 0 00007067 1F pop ds 0 00007068 3B06[0A00] cmp ax,[path_drive] ; if the drive's are same 0 0000706C 741B je chdir85 ; "CD" or "SUBST d:=d:path" 0 0000706E 26814F430010 or word [es:LDT_FLAGS + bx],LFLG_SUBST 0 00007074 8D3F lea di,[LDT_NAME + bx] ; ES:DI -> name 0 00007076 31C0 xor ax,ax 0 00007078 B94300 mov cx,LDT_FLAGS-LDT_NAME ; name can be this long 0 0000707B F2AE repne scasb ; look for terminating NUL 0 0000707D 29DF sub di,bx ; get # chars skipped 0 0000707F 4F dec di ; forget the NUL 0 00007080 83FF03 cmp di,3 ; root is special case again ! 0 00007083 7604 jbe chdir85 0 00007085 26897F4F mov [es:LDT_ROOTLEN + bx],di ; set new root position 544 <1> chdir85: 0 00007089 C3 ret 546 <1> 547 <1> ; CREATE FILE (CREAT) 548 <1> 549 <1> ; +----+----+----+----+----+----+----+----+----+----+ 550 <1> ; | 3C | name | mode | attrib | 551 <1> ; +----+----+----+----+----+----+----+----+----+----+ 552 <1> 553 <1> ; entry: 554 <1> ; ------ 555 <1> ; name: segmented address of ASCIIZ name 556 <1> ; mode: open mode for handle 557 <1> ; attrib: attribute for file 558 <1> 559 <1> ; exit: 560 <1> ; ----- 561 <1> ; AX: file handle or error code ( < 0) 562 <1> 563 <1> fdos_creat: 564 <1> ;---------- 0 0000708A E8[0000] call redir_asciiz_dev_offer ; offer it as a network device 0 0000708D E8DC0F call asciiz_dev_offer ; offer it as a local device 0 00007090 E8[0000] call redir_asciiz_file_offer ; offer it as a network file 0 00007093 E839FD call local_disk ; get MXdisk, switch stack 0 00007096 E88015 call mustbe_free_handle ; make sure we have spare handle 0 00007099 E84C0E call path_prep ; parse path, walk down the tree 0 0000709C E87810 call check_device ; is it a device ? 0 0000709F 7203 jc creat_disk 0 000070A1 E9[0000] jmp open_dev ; open as a device handle 574 <1> creat_disk: 0 000070A4 E80413 call chk_no_dot_or_wild 0 000070A7 F606[6600]08 test byte [fdos_pb+8],DA_VOLUME 0 000070AC 7405 jz creat_nolbl ; skip if not volume label 0 000070AE E8AC14 call mustbe_nolbl ; do we have an existing label ? 0 000070B1 EB2C jmp creat_new_file ; no, create one 580 <1> creat_nolbl: 0 000070B3 E8[0000] call finddfcbf ; find entry, ignore labels 0 000070B6 7427 jz creat_new_file ; skip if it doesn't exist yet 583 <1> 0 000070B8 E85417 call check_no_dir ; make sure not a directory 0 000070BB E85817 call check_ro ; check if file is read/only 0 000070BE E86E17 call close_if_open ; make sure not open by any process 587 <1> %ifdef PASSWORD 0 000070C1 E8161A call check_pwd_d ; check if PW req'd & supplied 589 <1> %endif 0 000070C4 8B1E[0000] mov bx,[dirp] 0 000070C8 8B471A mov ax,[DBLOCK1 + bx] ; release all blocks of the file 0 000070CB 31D2 xor dx,dx 0 000070CD 833E[0000]00 cmp word [dosfat],FAT32 ; is this a FAT32 file system? 0 000070D2 7503 jne creat10 ; no, proceed 0 000070D4 8B5714 mov dx,[DBLOCK1H + bx] ; yes, then we need the high word of the first cluster, too 596 <1> creat10: 0 000070D7 E8[0000] call delfat ; so it is truncated to zero size 0 000070DA E8[0000] call update_fat ; update file allocation table 0 000070DD EB03 jmp creat2 ; reinitialize directory entry 600 <1> 601 <1> creat_new_file: ; create new file - shared by MKNEW 0 000070DF E8[0000] call allocdir ; allocate a directory entry 603 <1> creat2: 0 000070E2 8B1E[0000] mov bx,[dirp] ; BX -> directory entry 0 000070E6 8D3F lea di,[DNAME + bx] ; DI -> name offset in dir buffer 0 000070E8 BE[2900] mov si,offset info_fcb+1 ; SI -> name offset in FCB 0 000070EB B90B00 mov cx,11 0 000070EE F3A4 rep movsb ; copy name into directory 0 000070F0 A1[6600] mov ax,[fdos_pb+8] ; get creation file attribute 0 000070F3 8B16[6400] mov dx,[fdos_pb+6] ; open in r/w, compatibilty mode 0 000070F7 A8D8 test al,~ (DA_RO+DA_SYSTEM+DA_HIDDEN+DA_ARCHIVE) 0 000070F9 7406 jz creat5 ; allow r/o, hidden, system, archive 0 000070FB A808 test al,DA_VOLUME ; failure as file, creating a label? 0 000070FD 7419 jz creat_access_err ; no, then it's really a problem 0 000070FF B280 mov dl,DHM_RO+DHM_LOCAL ; open in compatibility mode 616 <1> creat5: 0 00007101 0C20 or al,DA_ARCHIVE ; always create as new file 0 00007103 AA stosb ; update directory attributes 0 00007104 29C0 sub ax,ax ; zero out remainder of entry 0 00007106 B91400 mov cx,32-12 0 00007109 F3AA rep stosb ; zero remainder of entry 622 <1> 0 0000710B 53 push bx ; save dirp 0 0000710C 52 push dx ; save the open mode 0 0000710D E83119 call stamp_dir_entry ; set time and date in FCB 0 00007110 E8[0000] call update_dir ; update directory 0 00007113 58 pop ax ; restore open mode 0 00007114 5B pop bx ; restore dirp 0 00007115 E92615 jmp creat_handle ; now allocate file handle 630 <1> 631 <1> creat_access_err: 0 00007118 E944FD jmp fdos_ED_ACCESS ; return "access denied" 633 <1> 634 <1> 635 <1> ; OPEN FILE (OPEN) 636 <1> 637 <1> ; +----+----+----+----+----+----+----+----+----+----+ 638 <1> ; | 3D | name | mode | attrib | 639 <1> ; +----+----+----+----+----+----+----+----+----+----+ 640 <1> 641 <1> ; entry: 642 <1> ; ------ 643 <1> ; name: segmented address of ASCIIZ name 644 <1> ; mode: open mode 645 <1> ; attrib: file attrib for search (default = 16h) 646 <1> 647 <1> ; exit: 648 <1> ; ----- 649 <1> ; AX: file handle or error code ( < 0) 650 <1> 651 <1> fdos_open: 652 <1> ;--------- 0 0000711B E8[0000] call redir_asciiz_dev_offer ; offer it as a network device 0 0000711E E84B0F call asciiz_dev_offer ; offer it as a local device 0 00007121 E8[0000] call redir_asciiz_file_offer ; offer it as a network file 0 00007124 E8A8FC call local_disk ; get MXdisk, switch stack 0 00007127 E8EF14 call mustbe_free_handle ; make sure we have spare handle 0 0000712A E8BB0D call path_prep ; parse the path, go to bottom level 0 0000712D E8E70F call check_device 0 00007130 7203 jc open_disk 0 00007132 E9[0000] jmp open_dev ; open as a device 662 <1> open_disk: 0 00007135 E87612 call chk_no_wild ; we don't allow no wild cards here 0 00007138 E8[0000] call finddfcbf ; search by name 0 0000713B 744F jz open8 ; bail out if not found 0 0000713D A0[6600] mov al,byte ptr [fdos_pb+8] ; check requested attributes 667 <1> %ifdef PASSWORD 0 00007140 833E[0000]00 cmp word [dosfat],FAT32 ; FAT32 filesystem? 0 00007145 740F je open1 ; yes, then ignore passwords 0 00007147 837F0E00 cmp word ptr [DPWD + bx],0 0 0000714B 7409 je open1 0 0000714D F74714FF0F test word [DPWM + bx],0fffh ; no access rights set? 0 00007152 7402 jz open1 ; then assume it is unprotected 0 00007154 0C02 or al,DA_HIDDEN 675 <1> open1: 676 <1> %endif 0 00007156 F6D0 not al 0 00007158 2406 and al,DA_HIDDEN+DA_SYSTEM 0 0000715A 0C18 or al,DA_DIR+DA_VOLUME 0 0000715C 84470B test [DATTS + bx],al 0 0000715F 752E jnz open9 ; error if attrib not as requested 0 00007161 A1[6400] mov ax,[fdos_pb+6] ; determine open mode 683 <1> %ifdef PASSWORD 0 00007164 29D2 sub dx,dx ; assume no PW conflicts 685 <1> %endif 0 00007166 A803 test al,DHM_RW+DHM_WO ; test if read/only access 0 00007168 7411 jz open2 688 <1> %ifdef PASSWORD ; if write or r/w check writes 0 0000716A 81CA4404 or dx,PWM_W ; check for write password 690 <1> %endif 691 <1> ; mov bx,dirp ; get directory pointer 0 0000716E F6470B01 test byte [DATTS + bx],DA_RO ; read/only file? 0 00007172 7407 jz open2 ; no, skip FCB check 0 00007174 A90080 test ax,DHM_FCB ; if FCB open of read-only file 0 00007177 7416 jz open9 ; allow it, but adjust to read-only 0 00007179 24F0 and al,~ DHM_RWMSK ; open mode and proceed 697 <1> open2: 698 <1> %ifdef PASSWORD 0 0000717B A801 test al,DHM_WO ; will we try to read? 0 0000717D 7504 jnz open3 ; skip if not open for reading 0 0000717F 81CAAA0A or dx,PWM_R + PWM_E ; else check for read/exec password 702 <1> open3: 0 00007183 50 push ax ; save the open mode 0 00007184 92 xchg ax,dx ; AX = password modes to check for 0 00007185 E85A19 call check_pwd ; check for r/w passwords 0 00007188 58 pop ax 707 <1> %endif 0 00007189 E9A514 jmp open_handle ; now allocate file handle 709 <1> 710 <1> open8: 0 0000718C E9630A jmp fdos_ED_FILE ; "file not found" 712 <1> open9: 0 0000718F E9CDFC jmp fdos_ED_ACCESS ; return "access denied" error 714 <1> 715 <1> 716 <1> ; CLOSE FILE (CLOSE) 717 <1> 718 <1> ; +----+----+----+----+ 719 <1> ; | 3E | handle | 720 <1> ; +----+----+----+----+ 721 <1> 722 <1> ; entry: 723 <1> ; ------ 724 <1> ; handle: open file handle to be closed 725 <1> 726 <1> ; exit: 727 <1> ; ----- 728 <1> ; AX: 3Exx (where xx = # time it was open) or error code ( < 0) 729 <1> 730 <1> fdos_close: 731 <1> ;---------- 0 00007192 E8D715 call vfy_dhndl_ptr ; check file handle # 0 00007195 E8[0000] call redir_dhndl_offer 0 00007198 E834FC call local_disk ; get MXdisk, switch stack 0 0000719B E8A615 call check_handle ; check if legal file handle 0 0000719E 268B07 mov ax,[es:DHNDL_COUNT + bx] ; return # times file WAS open 0 000071A1 B43E mov ah,3Eh ; AH = MS_X_CLOSE 0 000071A3 A3[6C00] mov [fdos_ret],ax ; return 3Exx if successful 0 000071A6 721A jc close20 ; skip if character device close 740 <1> close_dhndl: 0 000071A8 E84616 call release_handle ; release file handle into pool 0 000071AB 36FF1E[1800] call far [ss:share_stub+S_CLOSE] ; call the fdos stub routine 0 000071B0 26FF0F dec word [es:DHNDL_COUNT + bx] ; one less XFN refers to this IFN 0 000071B3 26F747054080 test word [es:DHNDL_WATTR + bx],DHAT_REMOTE+DHAT_CLEAN 0 000071B9 7506 jnz close10 ; skip update if not dirty local file 0 000071BB E86815 call select_handle ; select the disk 0 000071BE E80906 call file_update ; update directory & FAT if written 748 <1> close10: 0 000071C1 C3 ret 750 <1> 751 <1> close20: ; handle refers to character device 0 000071C2 E9[0000] jmp close_dev ; close the device handle 753 <1> 754 <1> ; READ FROM FILE (READ) 755 <1> 756 <1> ; +----+----+----+----+----+----+----+----+----+----+ 757 <1> ; | 3F | handle | buffer | count | 758 <1> ; +----+----+----+----+----+----+----+----+----+----+ 759 <1> 760 <1> ; entry: 761 <1> ; ------ 762 <1> ; handle: open file handle 763 <1> ; buffer: buffer to read into 764 <1> ; count: max. number of bytes to read 765 <1> 766 <1> ; exit: 767 <1> ; ----- 768 <1> ; AX: byte count or error code ( < 0) 769 <1> 770 <1> fdos_read: 771 <1> ;--------- 0 000071C5 E8A415 call vfy_dhndl_ptr ; check file handle # 0 000071C8 26F747020100 test word [es:DHNDL_MODE + bx],DHM_WO 0 000071CE 755A jnz rw_ED_ACCESS ; fail if open write only 0 000071D0 E8[0000] call redir_dhndl_offer 0 000071D3 26F747058000 test word [es:DHNDL_WATTR + bx],DHAT_DEV 0 000071D9 754C jnz fdos_read_dev ; skip if character device 0 000071DB E8F1FB call local_disk ; get MXdisk, switch stack 0 000071DE E84015 call verify_handle ; check if legal file handle 0 000071E1 8B0E[6600] mov cx,[fdos_pb+8] ; get requested transfer length 781 <1> ; mov ax,es:DHNDL_POSLO[bx] ; If we get an error we want to have 782 <1> ; mov dx,es:DHNDL_POSHI[bx] ; xfer len adjusted for EOF (CopyIIpc) 783 <1> ; sub ax,es:DHNDL_SIZELO[bx] ; are we beyond EOF ? 784 <1> ; sbb dx,es:DHNDL_SIZEHI[bx] 0 000071E5 268B4715 mov ax,[es:DHNDL_POSLO + bx] 0 000071E9 262B4711 sub ax,[es:DHNDL_SIZELO + bx] 0 000071ED 89C2 mov dx,ax 0 000071EF 268B4717 mov ax,[es:DHNDL_POSHI + bx] 0 000071F3 261B4713 sbb ax,[es:DHNDL_SIZEHI + bx] 0 000071F7 268B4747 mov ax,[es:DHNDL_POSXLO + bx] 0 000071FB 261B4743 sbb ax,[es:DHNDL_SIZEXLO + bx] 0 000071FF 268B4749 mov ax,[es:DHNDL_POSXHI + bx] 0 00007203 261B4745 sbb ax,[es:DHNDL_SIZEXHI + bx] 794 <1> ; jb read2 ; beyond EOF already, no action required 795 <1> ; ja read2 ; more the 64K to go, no problems 0 00007207 7508 jnz read2 797 <1> ; cmp ax,cx ; do we want more than there is? 0 00007209 39CA cmp dx,cx ; do we want more than there is? 0 0000720B 7304 jae read2 ; yes, shorten the fdos_pb count 800 <1> ; sub fdos_pb+8,ax ; in case of a critical error 0 0000720D 2916[6600] sub [fdos_pb+8],dx ; in case of a critical error 802 <1> read2: 0 00007211 C606[0000]01 mov byte [fdrwflg],1 ; we're reading 0 00007216 C43E[6200] les di,[fdos_pb+4] ; get disk transfer address 0 0000721A E8[0000] call fdosrw ; read from file 0 0000721D 31C0 xor ax,ax ; return OK 0 0000721F 8706[6C00] xchg ax,[fdos_ret] ; get returned byte count 0 00007223 A3[6600] mov [fdos_pb+8],ax ; return in requested count 0 00007226 C3 ret 810 <1> 811 <1> fdos_read_dev: 0 00007227 E9[0000] jmp read_dev ; read from character device 813 <1> 814 <1> rw_ED_ACCESS: 0 0000722A BBFBFF mov bx,ED_ACCESS ; return access denied 0 0000722D C3 ret 817 <1> 818 <1> ; WRITE TO FILE (WRITE) 819 <1> 820 <1> ; +----+----+----+----+----+----+----+----+----+----+ 821 <1> ; | 40 | handle | buffer | count | 822 <1> ; +----+----+----+----+----+----+----+----+----+----+ 823 <1> 824 <1> ; entry: 825 <1> ; ------ 826 <1> ; handle: open file handle 827 <1> ; buffer: buffer to be wriiten 828 <1> ; count: max. number of bytes to write 829 <1> 830 <1> ; exit: 831 <1> ; ----- 832 <1> ; AX: byte count or error code ( < 0) 833 <1> 834 <1> fdos_write: 835 <1> ;---------- 0 0000722E E83B15 call vfy_dhndl_ptr ; check file handle # 0 00007231 26F747020300 test word [es:DHNDL_MODE + bx],DHM_WO+DHM_RW 0 00007237 74F1 jz rw_ED_ACCESS ; fail if not open in r/w or w mode? 0 00007239 E8[0000] call redir_dhndl_offer 0 0000723C 26F747058000 test word [es:DHNDL_WATTR + bx],DHAT_DEV 0 00007242 7520 jnz fdos_write_dev ; skip if not character device 0 00007244 E888FB call local_disk ; get MXdisk, switch stack 0 00007247 E8D714 call verify_handle ; check if legal file handle 0 0000724A C606[0000]00 mov byte [fdrwflg],0 ; we're writing 0 0000724F C43E[6200] les di,[fdos_pb+4] ; get disk transfer address 0 00007253 8B0E[6600] mov cx,[fdos_pb+8] ; get requested transfer length 0 00007257 E8[0000] call fdosrw ; write to file file 848 <1> 0 0000725A 31C0 xor ax,ax ; return OK 0 0000725C 8706[6C00] xchg ax,[fdos_ret] ; get returned byte count 0 00007260 A3[6600] mov [fdos_pb+8],ax ; return in requested count 0 00007263 C3 ret 853 <1> 854 <1> fdos_write_dev: 0 00007264 E9[0000] jmp write_dev ; write to character device 856 <1> 857 <1> ; DELETE FILE (UNLINK) 858 <1> 859 <1> ; +----+----+----+----+----+----+----+----+----+----+ 860 <1> ; | 41 | name | ***** | attrib | 861 <1> ; +----+----+----+----+----+----+----+----+----+----+ 862 <1> 863 <1> ; entry: 864 <1> ; ------ 865 <1> ; name: segmented address of ASCIIZ name 866 <1> ; attrib: delete mask (FCB only..) 867 <1> 868 <1> ; exit: 869 <1> ; ----- 870 <1> ; AX: 0000 or error code ( < 0) 871 <1> 872 <1> 873 <1> fdos_unlink: 874 <1> ;----------- 0 00007267 E8[0000] call redir_asciiz_offer 0 0000726A E862FB call local_disk ; get MXdisk, switch stack 0 0000726D E8780C call path_prep ; parse the path, go to bottom level 0 00007270 E8990E call chk_no_dev ; can't be a device 879 <1> ; look to see is the call is a remote 0 00007273 36833E[0000]00 cmp word [ss:remote_call],0 ; a 21/5D00 one or a local FCB one 0 00007279 7415 jz unlink1 ; neither, no wild cards allowed 0 0000727B 7916 jns unlink2 ; if it's an FCB call we need to check 0 0000727D F706[6600]0800 test word [fdos_pb+8],DA_VOLUME ; for deleting a VOLUME label 0 00007283 740E jz unlink2 0 00007285 E8FD12 call find_labelf ; lets find the volume label 0 00007288 7403 jz unlink4 ; reporting error if we don't match 0 0000728A E96EFC jmp kill_entry ; found it - delete it 888 <1> 889 <1> unlink4: 0 0000728D E96209 jmp fdos_ED_FILE ; return "file not found" 891 <1> 892 <1> unlink1: 0 00007290 E81B11 call chk_no_wild ; make sure not a wild card 894 <1> unlink2: 0 00007293 E8[0000] call setenddir ; search from the start 896 <1> 897 <1> ; We now skip any labels/dirs, returning ED_FILE if no other matches 898 <1> unlink3: 0 00007296 E8[0000] call finddfcb ; try to locate directory entry 0 00007299 74F2 jz unlink4 ; returning an error on failure 0 0000729B F6470B18 test byte [DATTS + bx],DA_DIR+DA_VOLUME 0 0000729F 75F5 jnz unlink3 ; make sure it isn't a label/directory 903 <1> 904 <1> unlink5: 905 <1> ; we have a match, so return ED_ACCESS if we can't find a file we can delete 0 000072A1 E82000 call unlink_attribs ; AL = attribs we can't delete 0 000072A4 740D jz unlink7 ; yes, go for it 0 000072A6 E8[0000] call finddfcb ; look for another entry 0 000072A9 75F6 jnz unlink5 ; try this one instead 0 000072AB E9B1FB jmp fdos_ED_ACCESS ; "access denied" if nothing deleted 911 <1> ; since we found at least 1 file 912 <1> 913 <1> ; we will delete at least one file, so now we succeed 914 <1> unlink6: 0 000072AE E81300 call unlink_attribs ; AL = attribs we can't delete 0 000072B1 7509 jnz unlink8 ; yes, go for it 917 <1> unlink7: 0 000072B3 E87315 call close_if_same_psp ; make sure not open by any process 919 <1> %ifdef PASSWORD 0 000072B6 E82118 call check_pwd_d ; check for password 921 <1> %endif 0 000072B9 E86A12 call kill_file ; delete file 923 <1> unlink8: 0 000072BC E8[0000] call finddfcb ; look for another entry 0 000072BF 75ED jnz unlink6 ; try and delete it if we find one 0 000072C1 E93AFC jmp update_dir_fat ; write out dirty directories/FAT 927 <1> 928 <1> 929 <1> unlink_attribs: 930 <1> ; On Entry: 931 <1> ; BX -> directory entry 932 <1> ; On Exit: 933 <1> ; AL = attribute mask which prevents deletion 934 <1> ; ZF = 1 if delete OK, ZF = 0 if file should be skipped 935 <1> ; 0 000072C4 A0[6600] mov al,byte ptr [fdos_pb+8] ; check attributes 937 <1> %ifdef PASSWORD 0 000072C7 833E[0000]00 cmp word [dosfat],FAT32 ; FAT32 filesystem? 0 000072CC 740F je unlink_attribs10 ; yes, then ignore passwords 0 000072CE 837F0E00 cmp word ptr [DPWD + bx],0 0 000072D2 7409 je unlink_attribs10 0 000072D4 F74714FF0F test word [DPWM + bx],0fffh ; no access rights set? 0 000072D9 7402 jz unlink_attribs10 ; then assume it is unprotected 0 000072DB 0C02 or al,DA_HIDDEN 945 <1> unlink_attribs10: 946 <1> %endif 0 000072DD F6D0 not al 0 000072DF 2407 and al,DA_HIDDEN+DA_SYSTEM+DA_RO 0 000072E1 0C18 or al,DA_DIR+DA_VOLUME 0 000072E3 84470B test [DATTS + bx],al ; should we delete this entry ? 0 000072E6 C3 ret 952 <1> 953 <1> 954 <1> ; GET/SET FILE POSITION (LSEEK) 955 <1> 956 <1> ; +----+----+----+----+----+----+----+----+----+----+ 957 <1> ; | 42 | handle | offset ! method | 958 <1> ; +----+----+----+----+----+----+----+----+----+----+ 959 <1> 960 <1> ; entry: 961 <1> ; ------ 962 <1> ; handle: open file handle 963 <1> ; offset: long integer offset 964 <1> ; method: 0 = begin, 1 = current, 2 = end of file 965 <1> 966 <1> ; exit: 967 <1> ; ----- 968 <1> ; AX: 0000 or error code ( < 0) 969 <1> ; offset: new offset 970 <1> 971 <1> fdos_lseek: 972 <1> ;---------- 0 000072E7 E88214 call vfy_dhndl_ptr ; check file handle # 0 000072EA E8[0000] call redir_dhndl_offer 0 000072ED E8DFFA call local_disk ; get MXdisk, switch stack 0 000072F0 26F6470580 test byte [es:DHNDL_ATTR + bx],DHAT_DEV 0 000072F5 7503 jnz lseek_dev ; skip a part if character device 0 000072F7 E84A14 call check_handle ; check if legal file handle 979 <1> lseek_dev: 0 000072FA A1[6200] mov ax,[fdos_pb+4] ; get 32-bit file offset 0 000072FD 8B16[6400] mov dx,[fdos_pb+6] ; into AX,DX 0 00007301 8B0E[6600] mov cx,[fdos_pb+8] ; get seek mode 0 00007305 E355 jcxz lseek4 ; seek from beginning 0 00007307 49 dec cx 0 00007308 740A jz lseek2 ; seek from current position 0 0000730A 49 dec cx 0 0000730B 742B jz lseek3 ; seek from end 0 0000730D B8F3FF mov ax,ED_DATA ; else invalid seek mode 0 00007310 E913FB jmp fdos_error ; return error code 990 <1> lseek1: 0 00007313 C3 ret ; return error code 992 <1> 993 <1> lseek2: ; seek mode 1: relative to position 994 <1> ; add ax,es:DHNDL_POSLO[bx] 995 <1> ; adc dx,es:DHNDL_POSHI[bx] 0 00007314 26014715 add [es:DHNDL_POSLO + bx],ax 0 00007318 26115717 adc [es:DHNDL_POSHI + bx],dx 0 0000731C 2683574700 adc word [es:DHNDL_POSXLO + bx],0 0 00007321 2683574900 adc word [es:DHNDL_POSXHI + bx],0 0 00007326 F7C20080 test dx,8000h ; negative offset? 0 0000732A 740A jz lseek2a 0 0000732C 26834747FF add word [es:DHNDL_POSXLO + bx],0ffffh; yes, then extend the sign to 64-bit 0 00007331 26835749FF adc word [es:DHNDL_POSXHI + bx],0ffffh 1004 <1> lseek2a: 0 00007336 EB3C jmp lseek4a ; update new position 1006 <1> 1007 <1> lseek3: ; seek mode 2: relative to end 1008 <1> ; add ax,es:DHNDL_SIZELO[bx] 1009 <1> ; adc dx,es:DHNDL_SIZEHI[bx] ; add file size + offset 0 00007338 50 push ax 0 00007339 268B4711 mov ax,[es:DHNDL_SIZELO + bx] 0 0000733D 26894715 mov [es:DHNDL_POSLO + bx],ax 0 00007341 268B4713 mov ax,[es:DHNDL_SIZEHI + bx] 0 00007345 26894717 mov [es:DHNDL_POSHI + bx],ax 0 00007349 268B4743 mov ax,[es:DHNDL_SIZEXLO + bx] 0 0000734D 26894747 mov [es:DHNDL_POSXLO + bx],ax 0 00007351 268B4745 mov ax,[es:DHNDL_SIZEXHI + bx] 0 00007355 26894749 mov [es:DHNDL_POSXHI + bx],ax 0 00007359 58 pop ax 0 0000735A EBB8 jmp lseek2 1021 <1> lseek4: ; seek mode 0: set absolute position 0 0000735C 26894715 mov [es:DHNDL_POSLO + bx],ax 0 00007360 26895717 mov [es:DHNDL_POSHI + bx],dx 0 00007364 A3[6200] mov [fdos_pb+4],ax ; set return values 0 00007367 8916[6400] mov [fdos_pb+6],dx 0 0000736B 26894F47 mov [es:DHNDL_POSXLO + bx],cx 0 0000736F 26894F49 mov [es:DHNDL_POSXHI + bx],cx 0 00007373 C3 ret 1029 <1> lseek4a: 0 00007374 26837F4700 cmp word [es:DHNDL_POSXLO + bx],0 0 00007379 7507 jne lseek4b 0 0000737B 26837F4900 cmp word [es:DHNDL_POSXHI + bx],0 0 00007380 7415 je lseek4d 1034 <1> lseek4b: 0 00007382 26837F47FF cmp word [es:DHNDL_POSXLO + bx],0ffffh 0 00007387 7507 jne lseek4c 0 00007389 26837F49FF cmp word [es:DHNDL_POSXHI + bx],0ffffh 0 0000738E 7407 je lseek4d 1039 <1> lseek4c: 0 00007390 31C0 xor ax,ax 0 00007392 48 dec ax 0 00007393 89C2 mov dx,ax 0 00007395 EB08 jmp lseek4e 1044 <1> lseek4d: 0 00007397 268B4715 mov ax,[es:DHNDL_POSLO + bx] 0 0000739B 268B5717 mov dx,[es:DHNDL_POSHI + bx] 1047 <1> lseek4e: 0 0000739F A3[6200] mov [fdos_pb+4],ax ; set return values 0 000073A2 8916[6400] mov [fdos_pb+6],dx 0 000073A6 C3 ret 1051 <1> 1052 <1> ; GET/SET FILE ATTRIBUTES (CHMOD) 1053 <1> 1054 <1> ; +----+----+----+----+----+----+----+----+----+----+ 1055 <1> ; | 43 | name | flag | attrib | 1056 <1> ; +----+----+----+----+----+----+----+----+----+----+ 1057 <1> ; | size | 1058 <1> ; +----+----+----+----+ 1059 <1> 1060 <1> ; entry: 1061 <1> ; ------ 1062 <1> ; name: pointer to ASCIIZ file name 1063 <1> ; flag: 00 = get attrib/size 1064 <1> ; 01 = set attrib 1065 <1> ; attrib: file attribute if flag=1 1066 <1> ; 1067 <1> ; exit: 1068 <1> ; ----- 1069 <1> ; AX: 0000 or error code ( < 0) 1070 <1> ; attrib: file attribute if flag=0 1071 <1> ; size: file size if flag=0 1072 <1> ; 1073 <1> %ifdef PASSWORD 1074 <1> ; entry: 1075 <1> ; ------ 1076 <1> ; name: pointer to ASCIIZ file name 1077 <1> ; flag: 02 = get password mode 1078 <1> ; 03 = set pw mode/password 1079 <1> ; 04 = get encrypted password 1080 <1> ; 05 = set encrypted password 1081 <1> ; attrib: password mode if flag = 3,5 1082 <1> ; dma: ascii password if flag = 3 1083 <1> ; encrypted password if flag = 5 1084 <1> ; 1085 <1> ; exit: 1086 <1> ; ----- 1087 <1> ; AX: 0000 or error code ( < 0) 1088 <1> ; attrib: file's attribute if flag = 0 1089 <1> ; password mode if flag = 2 1090 <1> ; encrypted password if flag = 4 1091 <1> %endif 1092 <1> %ifdef UNDELETE 1093 <1> ; entry: 1094 <1> ; ------ 1095 <1> ; name: pointer to ASCIIZ file name 1096 <1> ; flag: 80 = undelete file 1097 <1> ; 81 = purge file 1098 <1> ; dma: result of sucessful search 1099 <1> ; 1100 <1> ; exit: 1101 <1> ; ----- 1102 <1> ; AX: 0000 or error code ( < 0) 1103 <1> ; 1104 <1> %endif 1105 <1> 1106 <1> fdos_chmod: 1107 <1> ;---------- 1108 <1> %ifdef UNDELETE 0 000073A7 8B7602 mov si,[2 + bp] ; SI -> parameter block 0 000073AA 8A4406 mov al,[6 + si] ; AX = flag 0 000073AD 2C80 sub al,80h ; is it undelete or purge 0 000073AF 7240 jb fdos_chmod_path ; if so set 0 000073B1 3C01 cmp al,1 0 000073B3 773C ja fdos_chmod_path 0 000073B5 E817FA call local_disk ; get MXdisk, switch stack 0 000073B8 E8EC16 call select_from_DTA ; prepare for the search 0 000073BB C706[0000]0000 mov word [chdblk],0 ; don't assume sequential access 0 000073C1 C706[0200]0000 mov word [chdblk+2],0 0 000073C7 FF0E[0000] dec word [dcnt] ; retract so we find the same entry 0 000073CB E8EF11 call find_pending_delete ; did we find it ? 0 000073CE 743D jz chmod_notfound ; No, then skip 0 000073D0 E8FB0E call hdsblk ; AX = directory root cluster 0 000073D3 92 xchg ax,dx ; DX = dir cluster 0 000073D4 8B0E[0000] mov cx,[dcnt] ; CX = directory index for entry 0 000073D8 A1[6400] mov ax,[fdos_pb+6] ; get operation type 0 000073DB B40F mov ah,DELW_UNDEL ; assume we are about to undelete 0 000073DD 3C80 cmp al,80h ; is it undelete ? 0 000073DF 7402 je fdos_undelete_purge 0 000073E1 B40E mov ah,DELW_PURGE ; no, it must be purge entry 1130 <1> fdos_undelete_purge: 0 000073E3 A0[0000] mov al,[physical_drv] ; give delwatch a chance to do it 0 000073E6 36FF1E[0000] call far [ss:fdos_stub] 0 000073EB 722A jc fdos_ED_FUNCTION ; return error if DELWATCH not there 0 000073ED A3[6C00] mov [fdos_ret],ax ; else return result 0 000073F0 C3 ret 1136 <1> fdos_chmod_path: 1137 <1> %endif 0 000073F1 E8[0000] call redir_asciiz_offer 0 000073F4 E8D8F9 call local_disk ; get MXdisk, switch stack 1140 <1> 0 000073F7 E8EE0A call path_prep ; parse the path, go to bottom level 0 000073FA E8B10F call chk_no_wild ; can't have wildcards 0 000073FD E8[0000] call finddfcbf ; find first matching FCB 0 00007400 751B jnz chmod10 ; if we can't find a file/dir 0 00007402 E8CC0F call chk_for_root ; check if we are in the root 0 00007405 7506 jnz chmod_notfound ; if so return directory attribute 0 00007407 8B0E[6400] mov cx,[fdos_pb+6] ; but only for get attributes 0 0000740B E303 jcxz chmod_root ; other fall through to not found 1149 <1> chmod_notfound: 0 0000740D E9E207 jmp fdos_ED_FILE 1151 <1> chmod_root: 0 00007410 C706[6600]1000 mov word [fdos_pb+8],DA_DIR ; return directory attribute 0 00007416 C3 ret 1154 <1> 1155 <1> fdos_ED_FUNCTION: 0 00007417 B8FFFF mov ax,ED_FUNCTION ; invalid subfunction 0 0000741A E909FA jmp fdos_error 1158 <1> 1159 <1> chmod10: 0 0000741D 8B1E[0000] mov bx,[dirp] ; BX -> matching directory entry 0 00007421 8B471C mov ax,[DSIZE + bx] 0 00007424 A3[6800] mov [fdos_pb+10],ax 0 00007427 8B471E mov ax,[bx+DSIZE+2] 0 0000742A A3[6A00] mov [fdos_pb+12],ax 0 0000742D 31C0 xor ax,ax 0 0000742F 8A470B mov al,[DATTS + bx] ; get directory attributes 0 00007432 8B0E[6400] mov cx,[fdos_pb+6] ; get function # 0 00007436 E36B jcxz chmod30 ; always allow get attribs 1169 <1> %ifdef PASSWORD 0 00007438 80F905 cmp cl,5 ; validate sub-function number 0 0000743B 773E ja chmod15 0 0000743D B80000 mov ax,0 0 00007440 833E[0000]00 cmp word [dosfat],FAT32 ; FAT32 file system? 0 00007445 7403 je chmod11 ; yes, then this entry is used for high word of cluster instead 0 00007447 8B4714 mov ax,[DPWM + bx] ; assume return password mode 1176 <1> chmod11: 0 0000744A 25DD0D and ax,PWM_ANY ; isolate password mode bits 0 0000744D 80F902 cmp cl,2 ; is it get mode ? 0 00007450 7451 je chmod30 ; yes, just return it 0 00007452 50 push ax 0 00007453 51 push cx 0 00007454 E88816 call check_pwd_any ; check the password 0 00007457 59 pop cx 0 00007458 58 pop ax 0 00007459 8B16[6600] mov dx,[fdos_pb+8] ; DX = new attributes 0 0000745D 80F902 cmp cl,2 ; is it get mode ? 0 00007460 7724 ja chmod20 ; how about other password functions? 1188 <1> %else 1189 <1> cmp cl,1 ; validate sub-function number 1190 <1> ja chmod15 1191 <1> mov dx,[fdos_pb+8] ; DX = new attributes 1192 <1> %endif 1193 <1> ; Set new file attrib 1194 <1> ; BX = DIRP 1195 <1> ; DX = attrib 1196 <1> ; 0 00007462 F6C210 test dl,DA_DIR ; directory bit not allowed 0 00007465 750B jnz chmod12 0 00007467 32570B xor dl,[DATTS + bx] ; check which bits are changed 0 0000746A 80E2EF and dl,~ DA_DIR ; don't check or flip directory bit 0 0000746D F6C2D8 test dl,DA_FIXED ; trying to change the unchangeable? 0 00007470 7403 jz chmod13 1203 <1> chmod12: 0 00007472 E9EAF9 jmp fdos_ED_ACCESS ; return "access denied" 1205 <1> chmod13: 0 00007475 30570B xor [DATTS + bx],dl ; set new attributes 1207 <1> %ifdef PASSWORD 0 00007478 E98700 jmp chmod90 1209 <1> %else 1210 <1> jmp update_dir ; update directory 1211 <1> %endif 1212 <1> 1213 <1> chmod15: 0 0000747B B421 mov ah,PASSWD_CHMOD ; call out to SECURITY TSR 0 0000747D 36FF1E[0000] call far [ss:fdos_stub] 0 00007482 7293 jc fdos_ED_FUNCTION 0 00007484 EB7C jmp chmod90 1218 <1> 1219 <1> %ifdef PASSWORD 1220 <1> chmod20: 1221 <1> ; Password support for functions 3-5 1222 <1> ; BX = DIRP 1223 <1> ; CX = flag 1224 <1> ; DX = attrib 1225 <1> ; 0 00007486 53 push bx 0 00007487 51 push cx 0 00007488 52 push dx 0 00007489 BF2400 mov di,S_DENY_IF_OPEN ; check if file already open 0 0000748C E8A313 call check_with_share ; and stop if it is 0 0000748F 5A pop dx 0 00007490 59 pop cx 0 00007491 5B pop bx 0 00007492 31C0 xor ax,ax 0 00007494 833E[0000]00 cmp word [dosfat],FAT32 ; FAT32 filesystem? 0 00007499 7403 je chmod25 ; then assume no password set 0 0000749B 8B470E mov ax,[DPWD + bx] ; assume get encrypted password 1238 <1> chmod25: 0 0000749E 80F904 cmp cl,4 ; was it ? 0 000074A1 7504 jne chmod50 1241 <1> %endif ; yes, return encrypted password 1242 <1> chmod30: 0 000074A3 A3[6600] mov [fdos_pb+8],ax 0 000074A6 C3 ret 1245 <1> 1246 <1> 1247 <1> %ifdef PASSWORD 1248 <1> ; Password support for functions 3/5 1249 <1> ; BX = DIRP 1250 <1> ; CX = flag 1251 <1> ; DX = attrib 1252 <1> ; 1253 <1> chmod50: ; set password/password mode 0 000074A7 F6C680 test dh,80h ; assign new password? 0 000074AA 7427 jz chmod70 ; skip if mode change only 0 000074AC BF[3400] mov di,offset save_area ; ES:DI -> local structure 0 000074AF 1E push ds 0 000074B0 E84D14 call lds_si_dmaptr ; DS:SI -> users DMA address 0 000074B3 AD lodsw ; AX = possible encrypted password 0 000074B4 80F905 cmp cl,5 ; was it set encrypted password ? 0 000074B7 7405 je chmod60 0 000074B9 4E dec si ; no, the DMA buffer contains 0 000074BA 4E dec si ; an 8 character password so we 0 000074BB E86316 call hash_pwd ; compute password hash code 1265 <1> chmod60: 0 000074BE 1F pop ds 0 000074BF 833E[0000]00 cmp word [dosfat],FAT32 ; FAT32 filesystem? 0 000074C4 7407 je chmod65 ; then passwords do not apply 0 000074C6 804F0B02 or byte [DATTS + bx],DA_HIDDEN ; file will be hidden 0 000074CA 89470E mov [DPWD + bx],ax ; set new file password 1271 <1> chmod65: 0 000074CD 85C0 test ax,ax ; null password? 0 000074CF 7502 jnz chmod70 0 000074D1 31D2 xor dx,dx ; can't be protected.... 1275 <1> chmod70: 0 000074D3 B822F2 mov ax,~ PWM_ANY ; clear existing file 0 000074D6 833E[0000]00 cmp word [dosfat],FAT32 ; FAT32 file system? 0 000074DB 7403 je chmod75 ; then this entry cannot be used for passwords 0 000074DD 214714 and [DPWM + bx],ax ; password mode bits 1280 <1> chmod75: 0 000074E0 F7D0 not ax ; isolate password mode bits 0 000074E2 21C2 and dx,ax ; in new password mode 0 000074E4 7407 jz chmod80 ; if no protection, leave them off 0 000074E6 F6470B10 test byte [DATTS + bx],DA_DIR ; directories protected in all modes 0 000074EA 7401 jz chmod80 ; skip if not a directory 0 000074EC 92 xchg ax,dx ; force all modes on 1287 <1> chmod80: 0 000074ED 833E[0000]00 cmp word [dosfat],FAT32 ; FAT32 file system? 0 000074F2 740A je chmod85 ; then password not applicable 0 000074F4 095714 or [DPWM + bx],dx ; set password mode bits 0 000074F7 85D2 test dx,dx ; test if protection enabled 0 000074F9 7507 jnz chmod90 ; skip if any protection still active 0 000074FB 89570E mov [DPWD + bx],dx ; remove the password and hidden bit 1294 <1> chmod85: 0 000074FE 80670BFD and byte [DATTS + bx],~ DA_HIDDEN ; as file is no longer protected 1296 <1> %endif 1297 <1> chmod90: 0 00007502 E9[0000] jmp update_dir ; now update the directory 1299 <1> 1300 <1> 1301 <1> ; DUPLICATE FILE HANDLE (DUP) 1302 <1> 1303 <1> ; +----+----+----+----+----+----+ 1304 <1> ; | 45 | handle | newhnd | 1305 <1> ; +----+----+----+----+----+----+ 1306 <1> 1307 <1> ; entry: 1308 <1> ; ------ 1309 <1> ; handle: open file handle 1310 <1> 1311 <1> ; exit: 1312 <1> ; ----- 1313 <1> ; newhnd: new file handle 1314 <1> ; AX: duplicate file handle or error code ( < 0) 1315 <1> 1316 <1> fdos_dup: 1317 <1> ;-------- 0 00007505 E8F210 call find_xfn ; find new external file # 0 00007508 8B7602 mov si,[2 + bp] ; SI -> parameter block 0 0000750B 897C04 mov [4 + si],di ; save new handle # 0 0000750E 7304 jnc fdos_fdup ; share the code with DUP2 0 00007510 BBFCFF mov bx,ED_HANDLE ; can't find a handle 0 00007513 C3 ret 1324 <1> 1325 <1> ; FORCE DUPLICATE FILE HANDLE (DUP2) 1326 <1> 1327 <1> ; +----+----+----+----+----+----+ 1328 <1> ; | 46 | handle | newhnd | 1329 <1> ; +----+----+----+----+----+----+ 1330 <1> 1331 <1> ; entry: 1332 <1> ; ------ 1333 <1> ; handle: open file handle 1334 <1> ; newhnd: new file handle 1335 <1> 1336 <1> ; exit: 1337 <1> ; ----- 1338 <1> ; AX: duplicate file handle or error code ( < 0) 1339 <1> 1340 <1> fdos_fdup: 1341 <1> ;--------- 0 00007514 E85512 call vfy_dhndl_ptr ; check file handle # 0 00007517 E8B5F8 call local_disk ; get critical section locks 0 0000751A E8C413 call get_xftptr ; ES:DI -> XFN table 0 0000751D 722D jc dup_err ; we need one.. 0 0000751F 8B1E[6200] mov bx,[fdos_pb+4] ; get user file number (0-19) 0 00007523 39CB cmp bx,cx ; is it sensible ? 0 00007525 7325 jae dup_err 0 00007527 268039FF cmp byte ptr [es:di+bx],0FFh 0 0000752B 751F jne dup_err ; handle should be closed by PCMODE.. 0 0000752D E81412 call check_handle ; check if legal file handle 0 00007530 26FF07 inc word [es:DHNDL_COUNT + bx] ; another user 0 00007533 E8[0000] call dup_dev ; inform device driver it's happened 0 00007536 E8A813 call get_xftptr ; ES:DI -> XFT's 0 00007539 8B1E[6000] mov bx,[fdos_pb+2] ; get XFN to dup from 0 0000753D 268A01 mov al,[es:di+bx] ; get it's IFN 0 00007540 8B1E[6200] mov bx,[fdos_pb+4] ; BX = XFN to dup to 0 00007544 268801 mov [es:di+bx],al ; it gets same IFN 0 00007547 891E[6C00] mov [fdos_ret],bx ; return XFN to caller 0 0000754B C3 ret 1361 <1> 1362 <1> dup_err: ; complain someone stole my handle 0 0000754C E91712 jmp fdos_ED_H_MATCH 1364 <1> 1365 <1> ; GET CURRENT DIRECTORY 1366 <1> ; 1367 <1> ; +----+----+----+----+----+----+----+----+ 1368 <1> ; | 47 | drive | path | 1369 <1> ; +----+----+----+----+----+----+----+----+ 1370 <1> 1371 <1> ; entry: 1372 <1> ; ------ 1373 <1> ; drive: drive to get path for 1374 <1> ; path: address of 64 byte path buffer to be 1375 <1> ; filled in with current path 1376 <1> 1377 <1> ; exit: 1378 <1> ; ----- 1379 <1> ; BX: 0100 or error code 1380 <1> 1381 <1> fdos_curdir: 1382 <1> ;----------- 0 0000754F E87DF8 call local_disk ; it's a disk function 0 00007552 E8F40B call get_pb2_drive ; get specified drive in AL 0 00007555 E8[0000] call get_ldt ; ES:BX -> LDT_ for drive 0 00007558 7240 jc fdos_curdir30 0 0000755A 268B5743 mov dx,[es:LDT_FLAGS + bx] 0 0000755E F7C20080 test dx,LFLG_NETWRKD 0 00007562 7518 jnz fdos_curdir10 0 00007564 F7C20040 test dx,LFLG_PHYSICAL 0 00007568 7430 jz fdos_curdir30 0 0000756A E83008 call select_unique ; select the drive for media changes 0 0000756D 36C41E[0000] les bx,[ss:current_ldt] ; ES:BX -> LDT_ for this drive 0 00007572 26837F49FF cmp word [es:LDT_BLK + bx],0FFFFh ; is LDT valid 0 00007577 7503 jne fdos_curdir10 0 00007579 E8DB08 call rebuild_ldt_curdir ; no, better rebuild it 1397 <1> fdos_curdir10: 0 0000757C 1E push ds 0 0000757D 06 push es 0 0000757E 53 push bx ; save LDT 0 0000757F C43E[6200] les di,[fdos_pb+4] ; ES:DI -> destination buffer 0 00007583 5E pop si 0 00007584 1F pop ds ; DS:SI -> LDT 0 00007585 03744F add si,[LDT_ROOTLEN + si] ; skip the '\\server\dir' 0 00007588 AC lodsb ; eat the slash 0 00007589 E87D0F call check_slash ; if it is one.. 0 0000758C 7401 je fdos_curdir20 0 0000758E 4E dec si ; I didn't mean it! 1409 <1> fdos_curdir20: 0 0000758F E87A13 call copy_asciiz ; copy the string 0 00007592 1F pop ds 0 00007593 C706[6C00]0001 mov word [fdos_ret],100h ; return 100h for success 0 00007599 C3 ret 1414 <1> 1415 <1> fdos_curdir30: 0 0000759A E9B3F8 jmp fdos_ED_DRIVE ; naughty - it's a bad drive 1417 <1> 1418 <1> 1419 <1> ; GET DISK PARAMETER BLOCK 1420 <1> 1421 <1> ; +----+----+----+----+----+----+----+----+----+----+ 1422 <1> ; | 48 | drive | dpb | adjust | 1423 <1> ; +----+----+----+----+----+----+----+----+----+----+ 1424 <1> 1425 <1> ; entry: 1426 <1> ; ------ 1427 <1> ; drive: drive to get information about 1428 <1> ; (top bit of word set if free space not required) 1429 <1> 1430 <1> ; exit: 1431 <1> ; ----- 1432 <1> ; AX: 0000 or error code ( < 0) 1433 <1> ; dpb: address of DOS DPB (offset/segment) 1434 <1> ; adjust: delwatch adjustment of free space 1435 <1> 1436 <1> fdos_getdpb: 1437 <1> ;----------- 0 0000759D E8[0000] call redir_drv_offer 0 000075A0 E82CF8 call local_disk ; get MXdisk, switch stack 0 000075A3 E8A30B call get_pb2_drive ; get drive from parameter block 0 000075A6 E8FA07 call logical2physical ; AX = physical drive 0 000075A9 E8[0000] call select_physical_drv 0 000075AC F706[6000]0080 test word [fdos_pb+2],8000h ; free space required ? 0 000075B2 7512 jnz fdos_getdpb10 0 000075B4 E8[0000] call update_ddsc_free ; then make sure it is up to date 1446 <1> %ifdef DELWATCH 0 000075B7 31C9 xor cx,cx ; assume no adjustment 0 000075B9 B405 mov ah,DELW_SPACE 0 000075BB A0[0000] mov al,[physical_drv] ; now we call DELWATCH to 0 000075BE FF1E[0000] call far [fdos_stub] ; add pending deletes 0 000075C2 890E[6600] mov [fdos_pb+8],cx ; return free space adjust value 1452 <1> %endif 1453 <1> fdos_getdpb10: 0 000075C6 36C406[0000] les ax,[ss:current_ddsc] 0 000075CB A3[6200] mov [fdos_pb+4],ax 0 000075CE 8C06[6400] mov [fdos_pb+6],es 0 000075D2 C3 ret 1458 <1> 1459 <1> ; FLUSH BUFFERS 1460 <1> 1461 <1> ; +----+----+ 1462 <1> ; | 49 | 1463 <1> ; +----+----+ 1464 <1> 1465 <1> ; entry: 1466 <1> ; ------ 1467 <1> ; none 1468 <1> 1469 <1> ; exit: 1470 <1> ; ----- 1471 <1> ; none 1472 <1> 1473 <1> fdos_flush: 1474 <1> ;---------- 0 000075D3 E8F9F7 call local_disk ; be alone... 1476 <1> fdos_flush_local: 1477 <1> ; Entry point for people who already have the MX disk 0 000075D6 31D2 xor dx,dx ; starting with drive A 1479 <1> fdos_flush10: 0 000075D8 52 push dx 0 000075D9 E8[0000] call mark_ldt_unsure ; ask for LDT's to be relogged 0 000075DC 92 xchg ax,dx ; AL = drive to check 0 000075DD B440 mov ah,BF_DIRTY 0 000075DF E8[0000] call buffers_check ; any buffers on this drive? 0 000075E2 7409 jz fdos_flush20 ; skip flush if none 0 000075E4 E8[0000] call select_physical_drv ; select drive in AL 0 000075E7 E8[0000] call update_fat ; flush all FAT buffers 1488 <1> ; call update_dir ; dir always up to date 0 000075EA E8[0000] call update_dat ; flush all data buffers 1490 <1> fdos_flush20: 0 000075ED 5A pop dx 0 000075EE 8616[0000] xchg [adrive],dl 0 000075F2 E8[0000] call discard_all ; discard all buffers 0 000075F5 8616[0000] xchg [adrive],dl 0 000075F9 42 inc dx ; onto next drive 0 000075FA 3A16[0000] cmp dl,[phys_drv] 0 000075FE 72D8 jb fdos_flush10 0 00007600 B0FF mov al,0FFh ; AL = all drives 0 00007602 E9[0000] jmp hshdscrd ; forget about our hashing 1500 <1> ; ret 1501 <1> 1502 <1> 1503 <1> ; SELECT DRIVE 1504 <1> 1505 <1> ; +----+----+----+----+ 1506 <1> ; | 4A | drive | 1507 <1> ; +----+----+----+----+ 1508 <1> 1509 <1> ; entry: 1510 <1> ; ------ 1511 <1> ; drive: drive (zero based) to select as default drive 1512 <1> 1513 <1> ; exit: 1514 <1> ; ----- 1515 <1> ; current_dsk: drive (if legal) 1516 <1> 1517 <1> fdos_select: 1518 <1> ;----------- 0 00007605 E8C7F7 call local_disk ; cheap way to get MX 0 00007608 A1[6000] mov ax,[fdos_pb+2] ; AL = drive 0 0000760B E8[0000] call get_ldt ; ES:BX -> LDT for drive A 0 0000760E 89C2 mov dx,ax ; DL = logical drive 0 00007610 721B jc fdos_select10 ; no LDT, treat as physical=logical 0 00007612 268B4743 mov ax,[es:LDT_FLAGS + bx] ; get the LDT_FLAGS 0 00007616 A90080 test ax,LFLG_NETWRKD ; NETWORK drives are OK, but we must 0 00007619 7517 jnz fdos_select20 ; skip physical selection bit 0 0000761B A90040 test ax,LFLG_PHYSICAL 0 0000761E 7417 jz fdos_select30 ; skip physical selection bit 1529 <1> %ifdef JOIN 0 00007620 A90020 test ax,LFLG_JOINED ; JOINed drives are bad news 0 00007623 7512 jnz fdos_select30 ; so don't select one 1532 <1> %endif 0 00007625 268A07 mov al,[es:LDT_NAME + bx] ; get ASCII drive letter 0 00007628 E8E60E call toupper ; it was ascii 0 0000762B 2C41 sub al,'A' ; make it zero based 1536 <1> fdos_select10: 0 0000762D E8[0000] call get_ddsc ; ES:BX -> DDSC_ for drive 0 00007630 7205 jc fdos_select30 ; no, don't select 1539 <1> fdos_select20: 0 00007632 368816[0000] mov [ss:current_dsk],dl ; new logical disk selected 1541 <1> fdos_select30: 0 00007637 C3 ret 1543 <1> 1544 <1> ; EXECUTE CHILD (EXEC) 1545 <1> 1546 <1> ; +----+----+----+----+ 1547 <1> ; | 4B | pspseg | 1548 <1> ; +----+----+----+----+ 1549 <1> 1550 <1> ; entry: 1551 <1> ; ------ 1552 <1> ; pspseg: segment of child PSP 1553 <1> 1554 <1> ; exit: 1555 <1> ; ----- 1556 <1> ; AX: 0000h 1557 <1> 1558 <1> fdos_exec: 1559 <1> ;--------- 0 00007638 E894F7 call local_disk ; get MXdisk, switch stack 0 0000763B 8B0E[6000] mov cx,[fdos_pb+2] 0 0000763F E356 jcxz exec30 ; no duplicate handles if no new PSP 0 00007641 BF1800 mov di,offset PSP_XFT 0 00007644 8EC1 mov es,cx ; get child PSP 0 00007646 B91400 mov cx,XFNMAX ; get # of handles in child PSP 0 00007649 26890E3200 mov [es:PSP_XFNMAX],cx 0 0000764E 26893E3400 mov [es:PSP_XFTOFF],di 0 00007653 268C063600 mov [es:PSP_XFTSEG],es 0 00007658 B0FF mov al,0FFh ; assume all handles closed 0 0000765A F3AA rep stosb 0 0000765C 31F6 xor si,si ; start with XFN 0 1572 <1> exec10: 0 0000765E E88012 call get_xftptr ; ES:DI -> XFN table 0 00007661 7234 jc exec30 ; stop if none 0 00007663 01F7 add di,si 0 00007665 268A05 mov al,[es:di] ; get IFN of old handle 0 00007668 E8DD11 call ifn2dhndl ; ES:BX -> DHNDL_ 0 0000766B 7224 jc exec20 0 0000766D 268B0F mov cx,[es:DHNDL_COUNT + bx] ; skip files that aren't open 0 00007670 E31F jcxz exec20 0 00007672 26F6470610 test byte ptr [es:DHNDL_WATTR+1 + bx],DHAT_LOCAL/100h 0 00007677 7518 jnz exec20 ; don't inherit private files 0 00007679 26F6470380 test byte ptr [es:DHNDL_MODE+1 + bx],DHM_FCB/100h 0 0000767E 7511 jnz exec20 ; don't inherit FCB's 0 00007680 41 inc cx 0 00007681 26890F mov [es:DHNDL_COUNT + bx],cx ; increment in-use count 0 00007684 50 push ax 0 00007685 E8[0000] call dup_dev ; inform device driver it's happened 0 00007688 58 pop ax 0 00007689 8E06[6000] mov es,[fdos_pb+2] ; get child PSP 0 0000768D 26884418 mov [es:PSP_XFT + si],al ; inherit this IFN 1592 <1> exec20: 0 00007691 46 inc si ; next file handle 0 00007692 83FE14 cmp si,XFNMAX 0 00007695 72C7 jb exec10 ; inherit all file handles 1596 <1> exec30: 0 00007697 C3 ret 1598 <1> 1599 <1> 1600 <1> ; FIND FIRST FILE 1601 <1> 1602 <1> ; +----+----+----+----+----+----+----+----+----+----+ 1603 <1> ; | 4E | name | ***** | attrib | 1604 <1> ; +----+----+----+----+----+----+----+----+----+----+ 1605 <1> 1606 <1> ; entry: 1607 <1> ; ------ 1608 <1> ; name: pointer to ASCIIZ file name 1609 <1> ; attrib: attribute to be used in search 1610 <1> ; nb. API addition - attrib bit 7 set returns starting cluster 1611 <1> ; 1612 <1> ; exit: 1613 <1> ; ----- 1614 <1> ; AX: 0000 or error code ( < 0) 1615 <1> 1616 <1> ; Note: This call returns matching files in 1617 <1> ; the current DMA address and also saves 1618 <1> ; the BDOS state in the there. 1619 <1> ; 1620 <1> 1621 <1> fdos_first: 1622 <1> ;---------- 0 00007698 E8[0000] call redir_asciiz_dev_offer ; offer it as a network device 0 0000769B E8CE09 call asciiz_dev_offer ; offer it as a local device 0 0000769E E8[0000] call redir_asciiz_file_offer ; offer it as a network file 0 000076A1 E82BF7 call local_disk ; get MXdisk, switch stack 0 000076A4 E84108 call path_prep ; parse path, walk down the tree 0 000076A7 E86D0A call check_device ; if it a device 0 000076AA 730E jnc fdos_first10 0 000076AC A1[6600] mov ax,[fdos_pb+8] ; get search attribute 0 000076AF A2[2700] mov [attributes],al ; set for attribute match 0 000076B2 C706[0000]FFFF mov word [dcnt],0FFFFh ; search from beginning 0 000076B8 EB1C jmp search_next ; find next matching file 1634 <1> 1635 <1> fdos_first10: 0 000076BA E9[0000] jmp first_dev ; return device name 1637 <1> 1638 <1> next_deverr: ; NEXT after FIRST on device: 0 000076BD BBFEFF mov bx,ED_FILE ; "no more files" 0 000076C0 C3 ret 1641 <1> 1642 <1> ; FIND NEXT FILE 1643 <1> 1644 <1> ; +----+----+ 1645 <1> ; | 4F | 1646 <1> ; +----+----+ 1647 <1> 1648 <1> ; entry: 1649 <1> ; ------ 1650 <1> ; 1651 <1> ; exit: 1652 <1> ; ----- 1653 <1> ; AX: 0000 or error code ( < 0) 1654 <1> 1655 <1> ; Note: This call returns matching files in 1656 <1> ; the current DMA address and also saves 1657 <1> ; the BDOS state in the there. 1658 <1> ; 1659 <1> 1660 <1> fdos_next: 1661 <1> ;--------- 0 000076C1 1E push ds 0 000076C2 E83B12 call lds_si_dmaptr ; DS:SI -> users DMA address 0 000076C5 AD lodsw 0 000076C6 92 xchg ax,dx ; DH = local drive 0 000076C7 1F pop ds 0 000076C8 80FEFF cmp dh,0FFh ; check if FIRST was character device 0 000076CB 74F0 je next_deverr ; "no more files" if device 0 000076CD E8[0000] call redir_snext_offer 0 000076D0 E8FCF6 call local_disk ; get MXdisk, switch stack 0 000076D3 E8D113 call select_from_DTA ; prepare for the search 1672 <1> ; jmp search_next ; now go and look for next file 1673 <1> 1674 <1> search_next: 1675 <1> ;----------- 0 000076D6 C706[0000]0000 mov word [chdblk],0 ; don't assume sequential access 0 000076DC C706[0200]0000 mov word [chdblk+2],0 0 000076E2 A0[2700] mov al,[attributes] ; are we looking for a VOL label? 0 000076E5 A816 test al,DA_DIR+DA_SYSTEM+DA_HIDDEN 0 000076E7 7517 jnz search_n10 ; these bits take precedence 0 000076E9 A808 test al,DA_VOLUME ; searching for label? 0 000076EB 7413 jz search_n10 ; search for directory label only 1683 <1> %ifdef UNDELETE 0 000076ED 3C88 cmp al,DA_DELWATCH+DA_VOLUME 0 000076EF 7507 jne search_vol ; searching for pending delete entries? 0 000076F1 E8C90E call find_pending_delete ; did we find it ? 0 000076F4 7407 jz search_next_err ; No, then skip 0 000076F6 EB3B jmp search_n30 ; save search state for user 1689 <1> search_vol: 1690 <1> %endif 0 000076F8 E88D0E call find_label ; did we find it ? 0 000076FB 7536 jnz search_n30 ; save search state for user 1693 <1> search_next_err: 0 000076FD E94BF7 jmp fdos_ED_ROOM ; else end of directory 1695 <1> 1696 <1> search_n10: 0 00007700 C706[0000]0000 mov word [finddfcb_mask],0 ; find everything, including labels 0 00007706 E8[0000] call finddfcb ; find next matching entry 0 00007709 C706[0000]0008 mov word [finddfcb_mask],DA_VOLUME*256 ; restore mask 0 0000770F 74EC jz search_next_err ; if not found 0 00007711 A0[2700] mov al,[attributes] ; get attributes that we support 1702 <1> %ifdef PASSWORD 0 00007714 833E[0000]00 cmp word [dosfat],FAT32 ; FAT32 filesystem? 0 00007719 740F je search_n20 ; yes, then ignore passwords 0 0000771B 837F0E00 cmp word ptr [DPWD + bx],0 ; does it have a password? 0 0000771F 7409 jz search_n20 ; skip if not 0 00007721 F74714FF0F test word [DPWM + bx],0fffh ; no access rights set? 0 00007726 7402 jz search_n20 ; then assume it is unprotected 0 00007728 0C02 or al,DA_HIDDEN ; else include hidden files 1710 <1> search_n20: 1711 <1> %endif 0 0000772A F6D0 not al ; attributes we don't support 0 0000772C 241E and al,DA_DIR+DA_HIDDEN+DA_SYSTEM+DA_VOLUME 0 0000772E 84470B test [DATTS + bx],al ; any attributes we don't support 0 00007731 75CD jnz search_n10 ; then don't count this one 1716 <1> search_n30: 0 00007733 16 push ss 0 00007734 07 pop es 0 00007735 BF[0000] mov di,offset srch_buf ; ES:DI -> DMA search address 0 00007738 57 push di ; save for later 1721 <1> %ifdef JOIN 0 00007739 A0[1400] mov al,[fdos_hds_drv] ; save the PHYSICAL drive 1723 <1> %else 1724 <1> mov al,byte ptr [path_drive] ; save the specified drive 1725 <1> %endif 0 0000773C FEC0 inc al 0 0000773E AA stosb 0 0000773F 89FA mov dx,di ; remember start of name field 0 00007741 BE[2900] mov si,offset info_fcb+1 ; point at search FCB 0 00007744 B90B00 mov cx,11 0 00007747 F3A4 rep movsb ; save name for search 0 00007749 A0[2700] mov al,[attributes] ; get search attribute 0 0000774C AA stosb 1734 <1> 0 0000774D A1[0000] mov ax,[dcnt] 0 00007750 AB stosw ; save directory count 0 00007751 A1[0C00] mov ax,[fdos_hds_blk] ; get the directory block 0 00007754 AB stosw ; save the current block 0 00007755 A1[0E00] mov ax,[fdos_hds_blk+2] 0 00007758 AB stosw 1741 <1> 1742 <1> ; add di,4 ; skip 4 reserved bytes 0 00007759 83C702 add di,2 ; skip 2 reserved bytes 1744 <1> 0 0000775C 8B36[0000] mov si,[dirp] ; point to directory name 0 00007760 F606[2700]80 test byte [attributes],DA_CLUSTER ; is the caller requesting 0 00007765 7406 jz search_n35 ; the starting cluster ? 0 00007767 8B441A mov ax,[DBLOCK1 + si] ; pick it up from dir entry 0 0000776A 4F dec di ; and return at offset 13h 0 0000776B 4F dec di ; in DTA (WARNING - Lantastic 0 0000776C AB stosw ; server uses these bytes too..) 1752 <1> search_n35: 0 0000776D B91000 mov cx,32/2 0 00007770 F3A5 rep movsw ; location (also used by FCB search) 1755 <1> 0 00007772 5E pop si ; SI = offset srch_buf 0 00007773 E89011 call les_di_dmaptr ; ES:DI -> DMA address 0 00007776 16 push ss 0 00007777 1F pop ds ; DS:SI -> srch_buf 0 00007778 B91500 mov cx,21 0 0000777B F3A4 rep movsb ; copy from buffer to user DMA 0 0000777D 8B1E[0000] mov bx,[dirp] ; BX -> matching entry 0 00007781 8A470B mov al,[DATTS + bx] 0 00007784 AA stosb ; return directory attribute 0 00007785 8D7716 lea si,[DTIME + bx] 0 00007788 A5 movsw 0 00007789 A5 movsw ; return time, date 0 0000778A 46 inc si 0 0000778B 46 inc si ; skip starting cluster 0 0000778C A5 movsw 0 0000778D A5 movsw ; return file size 0 0000778E 8A470C mov al,[DSIZEX + bx] ; compute extended file size 0 00007791 88C4 mov ah,al 0 00007793 2407 and al,111b 0 00007795 80E4E0 and ah,11100000b 0 00007798 D0EC shr ah,1 0 0000779A D0EC shr ah,1 0 0000779C F706[6800]0100 test word [fdos_pb+10],1 ; use FAT+/LFN extensions? 0 000077A2 7408 jz search_n38 ; no, return 32bit file size 0 000077A4 08E0 or al,ah 0 000077A6 268845F5 mov [es:di - 11],al ; return extended file size 0 000077AA EB0C jmp search_n40 1783 <1> search_n38: 0 000077AC 08E0 or al,ah 0 000077AE 7408 je search_n40 ; if below 4 GB then skip 0 000077B0 83EF04 sub di,4 ; else go back to file size field 0 000077B3 31C0 xor ax,ax ; AX=FFFFh 0 000077B5 48 dec ax 0 000077B6 AB stosw 0 000077B7 AB stosw ; report 4 GB - 1 1791 <1> search_n40: 0 000077B8 E92B0B jmp unparse ; return file name 1793 <1> 1794 <1> ; COMMIT FILE (COMMIT) 1795 <1> 1796 <1> ; +----+----+----+----+ 1797 <1> ; | 50 | handle | 1798 <1> ; +----+----+----+----+ 1799 <1> 1800 <1> ; entry: 1801 <1> ; ------ 1802 <1> ; handle: open file handle to be flushed 1803 <1> 1804 <1> ; exit: 1805 <1> ; ----- 1806 <1> ; AX: 0000 or error code ( < 0) 1807 <1> 1808 <1> file_updt20: ; NO-OP for clean files 1809 <1> commit_dev: ; NO-OP on character devices 0 000077BB C3 ret 1811 <1> 1812 <1> fdos_commit: 1813 <1> ;----------- 0 000077BC E8AD0F call vfy_dhndl_ptr ; check file handle 0 000077BF E8[0000] call redir_dhndl_offer 0 000077C2 E80AF6 call local_disk ; get MXdisk, switch stack 0 000077C5 E8590F call verify_handle ; check if legal file handle 0 000077C8 72F1 jc commit_dev 1819 <1> ; jmp file_update ; update directory & FAT if written 1820 <1> 1821 <1> ; Update directory & File Allocation Table (partial close) 1822 <1> ; entry: ES:BX -> DHNDL_ 1823 <1> ; exit: ES:BX preserved 1824 <1> 1825 <1> Public file_update 1826 <1> 1827 <1> file_update: 1828 <1> ;----------- 0 000077CA 26F6470540 test byte [es:DHNDL_ATTR + bx],DHAT_CLEAN 0 000077CF 75EA jnz file_updt20 ; skip if file is clean 0 000077D1 268A471F mov al,[es:DHNDL_DCNTLO + bx] ; get directory count 0 000077D5 268A671E mov ah,[es:DHNDL_DCNTHI + bx] 0 000077D9 48 dec ax 0 000077DA A3[0000] mov [dcnt],ax ; set search position 0 000077DD 31C9 xor cx,cx ; find any entry 0 000077DF 890E[0000] mov [chdblk],cx ; non-sequential access 0 000077E3 890E[0200] mov [chdblk+2],cx 0 000077E7 06 push es 0 000077E8 53 push bx 0 000077E9 E8[0000] call getdir ; read the directory entry 0 000077EC 5B pop bx 0 000077ED 07 pop es 0 000077EE 85C0 test ax,ax ; did we find something? 0 000077F0 7456 jz file_updt10 ; skip if directory entry lost 0 000077F2 97 xchg ax,di ; DI -> directory entry in buffer 0 000077F3 804D0B20 or byte [DATTS + di],DA_ARCHIVE ; mark file as modified 1847 <1> ;;; call timestamp_dhndl ; record the current time 0 000077F7 268B4743 mov ax,[es:DHNDL_SIZEXLO + bx] ; get extended 6 bits for FAT+ 0 000077FB 88C4 mov ah,al ; shift the bits in place 0 000077FD 2407 and al,00000111b 0 000077FF 80E438 and ah,00111000b 0 00007802 D0E4 shl ah,1 0 00007804 D0E4 shl ah,1 0 00007806 08C4 or ah,al 0 00007808 8A450C mov al,[DSIZEX + di] ; get original DSIZEX byte 0 0000780B 2418 and al,00011000b ; save bits used WinNT 0 0000780D 08E0 or al,ah ; combine them with FAT+ bits 0 0000780F 88450C mov [DSIZEX + di],al ; and store them again 0 00007812 833E[0000]00 cmp word [dosfat],FAT32 ; is this a FAT32 file system? 0 00007817 7507 jne file_update05 ; no, then skip this entry 0 00007819 268B473B mov ax,[es:DHNDL_BLK1H + bx] ; get high word of 1st block in file 0 0000781D 894514 mov [DBLOCK1H + di],ax ; and store it in the dir entry 1863 <1> file_update05: 0 00007820 268B470B mov ax,[es:DHNDL_BLK1 + bx] ; 1st block in file 0 00007824 8D7D16 lea di,[DTIME + di] ; DI -> [time,date,block1,size] 0 00007827 06 push es 0 00007828 53 push bx 0 00007829 1E push ds 0 0000782A 8D770D lea si,[DHNDL_TIME + bx] 0 0000782D 1E push ds 0 0000782E 06 push es 0 0000782F 1F pop ds 0 00007830 07 pop es ; swap ES and DS 0 00007831 A5 movsw 0 00007832 A5 movsw ; copy time then date 0 00007833 AB stosw ; now 1st cluster 0 00007834 A5 movsw 0 00007835 A5 movsw ; finally file size 0 00007836 1F pop ds 0 00007837 E8[0000] call update_dir ; update directory 0 0000783A E8[0000] call update_fat ; flush dirty FAT 0 0000783D E8[0000] call update_dat ; flush all dirty data buffers 0 00007840 5B pop bx 0 00007841 07 pop es 0 00007842 26804F0540 or byte [es:DHNDL_ATTR + bx],DHAT_CLEAN 0 00007847 C3 ret ; only mark as clean AFTER it's written 1887 <1> 1888 <1> file_updt10: 0 00007848 B8FAFF mov ax,ED_H_MATCH ; can't find open file 0 0000784B A3[6C00] mov [fdos_ret],ax ; save error code 0 0000784E C3 ret 1892 <1> 1893 <1> ; CREATE NEW FILE 1894 <1> 1895 <1> ; +----+----+----+----+----+----+----+----+ 1896 <1> ; | 51 | name | mode | 1897 <1> ; +----+----+----+----+----+----+----+----+ 1898 <1> 1899 <1> ; entry: 1900 <1> ; ------ 1901 <1> ; name: segmented address of ASCIIZ name 1902 <1> ; mode: attribute for file 1903 <1> 1904 <1> ; exit: 1905 <1> ; ----- 1906 <1> ; AX: file handle or error code ( < 0) 1907 <1> 1908 <1> ; Note: The function is identical to CREATE FILE 1909 <1> ; with the exception that an error is returned 1910 <1> ; if the specified file already exists. 1911 <1> 1912 <1> fdos_mknew: 1913 <1> ;---------- 0 0000784F E8[0000] call redir_asciiz_offer 0 00007852 E87AF5 call local_disk ; get MXdisk, switch stack 0 00007855 E8C10D call mustbe_free_handle ; make sure we have spare handle 0 00007858 E84A0B call path_prep_chk ; parse path, walk down the tree 0 0000785B E8[0000] call finddfcbf ; check if we can find this one 0 0000785E 750D jnz mknew10 0 00007860 F606[6600]08 test byte [fdos_pb+8],DA_VOLUME 0 00007865 7403 jz mknew_nolbl ; skip if not volume label 0 00007867 E8F30C call mustbe_nolbl ; do we have an existing label ? 1923 <1> mknew_nolbl: 0 0000786A E972F8 jmp creat_new_file ; go ahead and create the file 1925 <1> mknew10: 0 0000786D B8B0FF mov ax,ED_EXISTS 0 00007870 E9B3F5 jmp fdos_error 1928 <1> 1929 <1> 1930 <1> ; LOCK/UNLOCK FILE DATA (LOCK/UNLOCK) 1931 <1> 1932 <1> ; +----+----+----+----+----+----+----+----+ 1933 <1> ; | 52 | handle | offset | 1934 <1> ; +----+----+----+----+----+----+----+----+ 1935 <1> ; | length | lock | 1936 <1> ; +----+----+----+----+----+----+ 1937 <1> 1938 <1> ; entry: 1939 <1> ; ------ 1940 <1> ; handle: open file handle 1941 <1> ; offset: long integer offset 1942 <1> ; length: long integer byte count 1943 <1> ; lock: 0 = lock, 1 = unlock 1944 <1> 1945 <1> ; exit: 1946 <1> ; ----- 1947 <1> ; AX: byte count or error code ( < 0) 1948 <1> 1949 <1> fdos_lock: 1950 <1> ;--------- 0 00007873 E8F60E call vfy_dhndl_ptr ; check file handle # 0 00007876 26F747058000 test word [es:DHNDL_WATTR + bx],DHAT_DEV 0 0000787C 751B jnz lock_dev ; skip if character device 0 0000787E E8[0000] call redir_dhndl_offer 0 00007881 E84BF5 call local_disk ; get MXdisk, switch stack 0 00007884 E8BD0E call check_handle ; check if legal file handle 0 00007887 B8FBFF mov ax,ED_ACCESS ; assume a problem 0 0000788A 720A jc lock_error ; can't lock/unlock device handles 0 0000788C BF[5E00] mov di,offset fdos_pb 0 0000788F 36FF1E[0000] call far [ss:share_stub+S_LOCKS] ; call the stub routine 0 00007894 7306 jnc lock_ret ; return error if we got one 1962 <1> lock_error: 0 00007896 E98DF5 jmp fdos_error ; can't do locking 1964 <1> 1965 <1> lock_dev: 0 00007899 BBFBFF mov bx,ED_ACCESS 1967 <1> lock_ret: 0 0000789C C3 ret 1969 <1> 1970 <1> 1971 <1> ; BUILD DDSC FROM BPB 1972 <1> 1973 <1> ; +----+----+----+----+----+----+----+----+----+----+ 1974 <1> ; | 53 | bpbptr ! ddscptr | 1975 <1> ; +----+----+----+----+----+----+----+----+----+----+ 1976 <1> 1977 <1> ; entry: 1978 <1> ; ------ 1979 <1> ; bpbptr: address of BPB 1980 <1> ; ddscptr: address of DDSC to be built 1981 <1> 1982 <1> ; exit: 1983 <1> ; ----- 1984 <1> ; 0000 or error code ( < 0) 1985 <1> 1986 <1> fdos_mkddsc: 1987 <1> ;----------- 0 0000789D 1E push ds 0 0000789E 8B7602 mov si,[2 + bp] ; SI -> parameter block 0 000078A1 8B4C0A mov cx,[10 + si] ; signatures for extended function 0 000078A4 8B540C mov dx,[12 + si] 0 000078A7 C47C06 les di,[6 + si] ; ES:DI -> DDSC 0 000078AA C57402 lds si,[2 + si] ; DS:SI -> BPB 1994 <1> 0 000078AD 81F95845 cmp cx,4558h ; does the first signature match? 0 000078B1 750B jne mkddsc_noext ; no, execute normal function 0 000078B3 81FA5241 cmp dx,4152h ; does the second signature match? 0 000078B7 7505 jne mkddsc_noext ; no, proceed with normal function 0 000078B9 E80D00 call bpb2ddsc ; convert BPB to DDSC 0 000078BC EB03 jmp mkddsc_ext 2001 <1> mkddsc_noext: 0 000078BE E80400 call bpb2ddsc_noext ; convert BPB to normal DDSC (without extended drive info) 2003 <1> mkddsc_ext: 0 000078C1 31DB xor bx,bx ; no error 0 000078C3 1F pop ds ; restore segment register 0 000078C4 C3 ret 2007 <1> 2008 <1> bpb2ddsc_noext: 0 000078C5 B300 mov bl,0 ; do not build extended DDSC 0 000078C7 EB02 jmp bpb2ddsc02 2011 <1> bpb2ddsc: 2012 <1> ;-------- 2013 <1> ; build a DDSC from a BPB, leavinf UNIT, RUNIT, DEVICE, FIRST, and LINK fields 2014 <1> ; unchanged 2015 <1> ; On Entry: 2016 <1> ; DS:SI -> source BPB 2017 <1> ; ES:DI -> destination DDSC 2018 <1> ; On Exit: 2019 <1> ; None 0 000078C9 B301 mov bl,1 ; build extended DDSC (default case) 2021 <1> bpb2ddsc02: 0 000078CB AD lodsw ; get sector size in bytes 0 000078CC 26894502 mov [es:DDSC_SECSIZE + di],ax 2024 <1> 0 000078D0 31C0 xor ax,ax 0 000078D2 AC lodsb ; get sectors/allocation unit 2027 <1> ; dec ax ; get cluster mask 0 000078D3 FEC8 dec al ; get cluster mask 0 000078D5 26884504 mov [es:DDSC_CLMSK + di],al ; store cluster mask 0 000078D9 AD lodsw ; get FAT address 0 000078DA 26894506 mov [es:DDSC_FATADDR + di],ax 2032 <1> 0 000078DE AC lodsb ; get # of fats 0 000078DF 26884508 mov [es:DDSC_NFATS + di],al 0 000078E3 98 cbw ; make it a word value 0 000078E4 92 xchg ax,dx ; and keep in DX 2037 <1> 0 000078E5 AD lodsw ; get # of directory entries 0 000078E6 26894509 mov [es:DDSC_DIRENT + di],ax 2040 <1> 0 000078EA AD lodsw ; get # of sectors total in image 0 000078EB 50 push ax ; save disk size for later 2043 <1> 0 000078EC AC lodsb ; get FAT id byte 0 000078ED 26884517 mov [es:DDSC_MEDIA + di],al ; set media byte 2046 <1> 0 000078F1 AD lodsw ; get # of sectors in a fat 0 000078F2 2689450F mov [es:DDSC_NFATRECS + di],ax ; set FAT size 2049 <1> ; mov es:word ptr DDSC_BFATRECS[di],ax ; FAT size (32-bit) 2050 <1> ; mov es:word ptr DDSC_BFATRECS+2[di],0 2051 <1> 0 000078F6 268B450F mov ax,word ptr [es:DDSC_NFATRECS + di] 0 000078FA F7E2 mul dx ; AX = FAT size 0 000078FC 26034506 add ax,[es:DDSC_FATADDR + di] ; AX = 1st directory sector 0 00007900 26894511 mov [es:DDSC_DIRADDR + di],ax ; set root directory address 2056 <1> 0 00007904 83C608 add si,2+2+4 ; skip SPT, NHEADS, BIGHIDDEN 2058 <1> 0 00007907 268B4D02 mov cx,[es:DDSC_SECSIZE + di] 0 0000790B B82000 mov ax,32 ; size of single directory entry 0 0000790E 26F76509 mul word [es:DDSC_DIRENT + di] ; AX/DX = root directory bytes 0 00007912 01C8 add ax,cx ; round up sector size 0 00007914 48 dec ax ; in case of odd number 0 00007915 F7F1 div cx ; convert to whole sectors 0 00007917 26034511 add ax,[es:DDSC_DIRADDR + di] ; add in base of root directory 0 0000791B 2689450B mov [es:DDSC_DATADDR + di],ax ; set this as first cluster address 2067 <1> ; mov es:DDSC_BDATADDR[di],ax ; also make this 32-bit value for now 2068 <1> ; mov es:DDSC_BDATADDR+2[di],0 2069 <1> 0 0000791F 58 pop ax ; recover total disk size 0 00007920 31D2 xor dx,dx ; assume 16 bit number 0 00007922 85C0 test ax,ax ; test for big drive 0 00007924 7505 jnz bpb2ddsc10 ; skip if not large drive 2074 <1> ; lodsw ; get low word of size 2075 <1> ; mov dx,[si] ; get high word of size 0 00007926 8B04 mov ax,[si] ; get low word of size 0 00007928 8B5402 mov dx,[2 + si] ; get high word of size 2078 <1> bpb2ddsc10: ; AX/DX = disk size in sectors 0 0000792B 83C604 add si,4 0 0000792E 262B450B sub ax,[es:DDSC_DATADDR + di] ; subtract non-data portion 0 00007932 83DA00 sbb dx,0 2082 <1> 0 00007935 31C9 xor cx,cx ; CL = cluster shift 0 00007937 268A6D04 mov ch,[es:DDSC_CLMSK + di] ; CH = cluster mask 2085 <1> bpb2ddsc20: ; count # of 1 bits 0 0000793B D0ED shr ch,1 ; shift right mask 0 0000793D 7307 jnc bpb2ddsc30 ; skip if all 1 bits shifted out 0 0000793F 41 inc cx ; count another 1 bit 0 00007940 D1EA shr dx,1 0 00007942 D1D8 rcr ax,1 ; div by two 0 00007944 EBF5 jmp bpb2ddsc20 ; repeat until all 1's counted 2092 <1> bpb2ddsc30: ; CL = log2 (CH) 0 00007946 26884D05 mov [es:DDSC_CLSHF + di],cl ; set cluster shift 0 0000794A 40 inc ax ; clusters 0/1 reserved (+2), and we 0 0000794B 2689450D mov [es:DDSC_NCLSTRS + di],ax ; want max (-1), so +1 2096 <1> ; mov es:word ptr DDSC_BCLSTRS[di],ax ; make this the default 32-bit value, too 0 0000794F 31C0 xor ax,ax 2098 <1> ; mov es:word ptr DDSC_BCLSTRS+2[di],ax 0 00007951 2689451D mov [es:DDSC_BLOCK + di],ax ; next block = 0 2100 <1> ; mov es:word ptr DDSC_BBLOCK[di],ax 2101 <1> ; mov es:word ptr DDSC_BBLOCK+2[di],ax 0 00007955 48 dec ax 0 00007956 2689451F mov [es:DDSC_FREE + di],ax ; free space = -1 (unknown) 2104 <1> ; mov es:word ptr DDSC_BFREE[di],ax 2105 <1> ; mov es:word ptr DDSC_BFREE+2[di],ax 2106 <1> 0 0000795A 26837D0900 cmp word [es:DDSC_DIRENT + di],0 ; is this an extended BPB? 0 0000795F 7403 je bpb2ddsc40 ; yes 0 00007961 E9C200 jmp bpb2ddsc50 2110 <1> 2111 <1> bpb2ddsc40: 0 00007964 80FB01 cmp bl,1 ; build extended DDSC? 0 00007967 7403 jz bpb2ddsc41 ; yes, proceed with extended info 0 00007969 E9BA00 jmp bpb2ddsc50 ; no, then skip the rest 2115 <1> bpb2ddsc41: 0 0000796C AD lodsw ; get low word of sectors per FAT 0 0000796D 26894533 mov word ptr [es:DDSC_BFATRECS + di],ax 0 00007971 AD lodsw ; get high word 0 00007972 26894535 mov word ptr [es:DDSC_BFATRECS+2 + di],ax 0 00007976 AD lodsw ; get FAT mirroring flags 0 00007977 26894525 mov [es:DDSC_FSFLAGS + di],ax 0 0000797B AD lodsw ; get file system version 0 0000797C 2689453F mov [es:DDSC_FSVER + di],ax 0 00007980 AD lodsw ; get low word of root start cluster 0 00007981 26894537 mov word ptr [es:DDSC_FSROOT + di],ax 0 00007985 AD lodsw ; get high word 0 00007986 26894539 mov word ptr [es:DDSC_FSROOT+2 + di],ax 0 0000798A AD lodsw ; get sector number of file system info sector 0 0000798B 263B4506 cmp ax,[es:DDSC_FATADDR + di] ; is the info sector below the FAT? 0 0000798F 7305 jae bpb2ddsc41a ; no, it must be invalid 0 00007991 83F800 cmp ax,0 ; same as boot sector? 0 00007994 7503 jnz bpb2ddsc41b ; if yes, that does not make sense 2133 <1> bpb2ddsc41a: 0 00007996 B8FFFF mov ax,0ffffh ; so just assume there is none 2135 <1> bpb2ddsc41b: 0 00007999 26894527 mov [es:DDSC_FSINFO + di],ax 0 0000799D AD lodsw ; get sector number of backup boot sector 0 0000799E 26894529 mov [es:DDSC_BOOTBAK + di],ax 2139 <1> 0 000079A2 26C74511FFFF mov word [es:DDSC_DIRADDR + di],0ffffh ; special case for FAT32 0 000079A8 26FF7535 push word ptr [es:DDSC_BFATRECS+2 + di] ; multiply sectors per FAT 0 000079AC 26FF7533 push word ptr [es:DDSC_BFATRECS + di] 0 000079B0 B80000 mov ax,0 ; with number of FATs 0 000079B3 50 push ax 0 000079B4 26FF7508 push word ptr [es:DDSC_NFATS + di] 0 000079B8 83EC08 sub sp,8 ; and reserve space for result on stack 0 000079BB E8[0000] call mul32 0 000079BE 58 pop ax ; get low dword of result 0 000079BF 5A pop dx 0 000079C0 83C40C add sp,12 ; clean up the stack 0 000079C3 26034506 add ax,[es:DDSC_FATADDR + di] ; compute start of data area 0 000079C7 83D200 adc dx,0 0 000079CA 2689452B mov word ptr [es:DDSC_BDATADDR + di],ax 0 000079CE 2689552D mov word ptr [es:DDSC_BDATADDR+2 + di],dx 0 000079D2 2689450B mov word ptr [es:DDSC_DATADDR + di],ax ; use 16-bit field as well 0 000079D6 83FA00 cmp dx,0 ; does this fit into 16-bit 0 000079D9 7406 je bpb2ddsc42 ; yes, then leave it 0 000079DB 26C7450B0000 mov word ptr [es:DDSC_DATADDR + di],0 ; else mark this entry as invalid 2159 <1> bpb2ddsc42: 0 000079E1 8B44EC mov ax,[si-20] ; get low word of size 0 000079E4 8B54EE mov dx,[si-18] ; get high word of size 0 000079E7 262B452B sub ax,word ptr [es:DDSC_BDATADDR + di] ; subtract non-data portion 0 000079EB 261B552D sbb dx,word ptr [es:DDSC_BDATADDR+2 + di] 0 000079EF 31C9 xor cx,cx 0 000079F1 268A4D05 mov cl,[es:DDSC_CLSHF + di] ; cluster shift value 0 000079F5 84C9 test cl,cl ; cluster size one? 0 000079F7 7406 jz bpb2ddsc44 2168 <1> bpb2ddsc43: 0 000079F9 D1EA shr dx,1 ; divide by two 0 000079FB D1D8 rcr ax,1 0 000079FD E2FA loop bpb2ddsc43 2172 <1> bpb2ddsc44: 0 000079FF 83C001 add ax,1 ; +1 to get number of highest cluster 0 00007A02 83D200 adc dx,0 0 00007A05 2689452F mov word ptr [es:DDSC_BCLSTRS + di],ax 0 00007A09 26895531 mov word ptr [es:DDSC_BCLSTRS+2 + di],dx 0 00007A0D 31C0 xor ax,ax 0 00007A0F 26C7450D0000 mov word [es:DDSC_NCLSTRS + di],0 0 00007A15 2689453B mov word ptr [es:DDSC_BBLOCK + di],ax ; next block = 0 0 00007A19 2689453D mov word ptr [es:DDSC_BBLOCK+2 + di],ax 0 00007A1D 48 dec ax 0 00007A1E 26894521 mov word ptr [es:DDSC_BFREE + di],ax ; free space = -1 (unknown) 0 00007A22 26894523 mov word ptr [es:DDSC_BFREE+2 + di],ax 2184 <1> 2185 <1> bpb2ddsc50: 0 00007A26 C3 ret 2187 <1> 2188 <1> 2189 <1> ; DIRECT DISK IO 2190 <1> 2191 <1> ; +----+----+----+----+----+----+ 2192 <1> ; | 54 |drv | op |nsectors | 2193 <1> ; +----+----+----+----+----+----+----+----+ 2194 <1> ; | startsec | dma address | 2195 <1> ; +----+----+----+----+----+----+----+----+ 2196 <1> 2197 <1> ; entry: 2198 <1> ; ------ 2199 <1> ; param block set up for direct disk IO 2200 <1> 2201 <1> ; exit: 2202 <1> ; ----- 2203 <1> ; AX = 0, or error code 2204 <1> ; 2205 <1> 2206 <1> DIO_25_READ_OP equ 1 2207 <1> DIO_26_WRITE_OP equ 2 2208 <1> 2209 <1> fdos_ddio: 2210 <1> ;--------- 2211 <1> ; Used by emulator for Int 25H/26H disk calls to BIOS 2212 <1> ; 2213 <1> ; entry: dio = offset of parameter block in user data segment 2214 <1> ; 2215 <1> ; exit: AX = return code from BIOS 2216 <1> 0 00007A27 E8A5F3 call local_disk ; get the MX 0 00007A2A A1[6000] mov ax,[fdos_pb+2] ; AX = logical drive 0 00007A2D E87303 call logical2physical ; AX = physical drive 0 00007A30 E8[0000] call get_ddsc ; make sure this drive is valid 0 00007A33 725F jc fdos_ddio30 ; bail if not 0 00007A35 A2[0000] mov [adrive],al ; remember this unit 0 00007A38 B80400 mov ax,CMD_INPUT+0*256 ; disk read operation of system area 0 00007A3B 803E[6100]02 cmp byte [fdos_pb+3],DIO_26_WRITE_OP 0 00007A40 751C jne fdos_ddio10 0 00007A42 B8FFFF mov ax,0FFFFh 0 00007A45 2689471F mov [es:DDSC_FREE + bx],ax ; free space = -1 (unknown) 0 00007A49 833E[0000]00 cmp word [dosfat],FAT32 ; FAT32 drive? 0 00007A4E 7508 jne fdos_ddio05 ; no, then skip 0 00007A50 26894721 mov word ptr [es:DDSC_BFREE + bx],ax ; free space = -1 (unknown) 0 00007A54 26894723 mov word ptr [es:DDSC_BFREE+2 + bx],ax 2232 <1> fdos_ddio05: 0 00007A58 E8[0000] call hshdscrd ; discard hashing info for all drives (AL=FF) 0 00007A5B B80801 mov ax,CMD_OUTPUT+1*256 ; disk write operation of system area 2235 <1> fdos_ddio10: 0 00007A5E 8826[0000] mov [rwmode],ah ; save read/write of system area 0 00007A62 8826[0500] mov [req_hdr+5],ah ; (so driver can get the hint) 0 00007A66 BB[0000] mov bx,offset req_hdr ; we will build request here 0 00007A69 884702 mov [RH_CMD + bx],al ; save the command 0 00007A6C A1[6200] mov ax,[fdos_pb+4] ; AX = # sectors 0 00007A6F 894712 mov [RH4_COUNT + bx],ax ; set requested sector count 0 00007A72 C406[6400] les ax,[fdos_pb+6] ; pick up 32-bit record address 0 00007A76 A3[0000] mov word ptr [pblock],ax 0 00007A79 8C06[0200] mov word ptr [pblock+2],es 0 00007A7D C406[6800] les ax,[fdos_pb+10] ; ES:AX -> DMA seg 0 00007A81 89470E mov [RH4_BUFOFF + bx],ax 0 00007A84 8C4710 mov [RH4_BUFSEG + bx],es 0 00007A87 E8[0000] call ddioif ; go do it 0 00007A8A 7907 jns fdos_ddio20 ; did we have a problem ? 0 00007A8C 98 cbw ; AX = base error 0 00007A8D 83C0ED add ax,ED_PROTECT ; "add" in BIOS error code 0 00007A90 A3[6C00] mov [fdos_ret],ax ; save return code 2253 <1> fdos_ddio20: 0 00007A93 C3 ret 2255 <1> 2256 <1> fdos_ddio30: 0 00007A94 E9B9F3 jmp fdos_ED_DRIVE ; return bad drive error 2258 <1> 2259 <1> 2260 <1> ; EXPAND FILE NAME 2261 <1> 2262 <1> ; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+ 2263 <1> ; | 55 | relative name | | absolute name | 2264 <1> ; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+ 2265 <1> 2266 <1> ; entry: 2267 <1> ; ------ 2268 <1> ; relative name: segmented address of ASCIIZ name 2269 <1> ; absolute name: segmented address of ASCIIZ name 2270 <1> 2271 <1> ; exit: 2272 <1> ; ----- 2273 <1> ; AX = BX: 0000 or error code ( < 0) 2274 <1> 2275 <1> fdos_expand: 2276 <1> ;----------- 0 00007A97 E8[0000] call redir_asciiz_dev_offer ; is it a networked device ? 0 00007A9A E8CF05 call asciiz_dev_offer ; see it we are expanding a device name 0 00007A9D E82FF3 call local_disk ; get MXdisk, switch stack 0 00007AA0 1E push ds 0 00007AA1 C436[6000] les si,[fdos_pb+2] ; get relative name buffer 0 00007AA5 268B04 mov ax,[es:si] ; get 1st two chars of path 0 00007AA8 E8550A call check_dslash ; is it a '\\' form ? 0 00007AAB 7414 je fdos_expand10 0 00007AAD BBFEFF mov bx,ED_FILE 0 00007AB0 84C0 test al,al 2287 <1> ; jz fdos_expand60 0 00007AB2 7503 jnz fdos_expand05 0 00007AB4 E9B000 jmp fdos_expand60 2290 <1> fdos_expand05: 0 00007AB7 E8570A call toupper ; work on premise we have drive 0 00007ABA 2C41 sub al,'A' ; specified in relative name 0 00007ABC 80EC3A sub ah,':' ; did we have ? 0 00007ABF 7403 je fdos_expand20 ; if so use it 2295 <1> fdos_expand10: 0 00007AC1 A0[0000] mov al,[current_dsk] ; use current drive 2297 <1> fdos_expand20: 0 00007AC4 3A06[0000] cmp al,[last_drv] ; is it a legal drive 2299 <1> ; jae fdos_expand50 0 00007AC8 7203 jb fdos_expand21 0 00007ACA E99700 jmp fdos_expand50 2302 <1> fdos_expand21: 2303 <1> 2304 <1> ; we should check for a media change so select_logical_drv seems to be 2305 <1> ; a better solution 2306 <1> ; call get_ldt ; ES:BX -> LDT_ for drive 2307 <1> ; jc fdos_expand40 ; no LDT at init - copy relative path 2308 <1> ; mov word ptr current_ldt,bx 2309 <1> ; mov word ptr current_ldt+WORD,es 0 00007ACD E8[0000] call select_logical_drv 0 00007AD0 C41E[0000] les bx,[current_ldt] 2312 <1> 0 00007AD4 26F747430040 test word [es:LDT_FLAGS + bx],LFLG_PHYSICAL 2314 <1> ; jz fdos_expand50 ; make sure it's a valid drive 0 00007ADA 7503 jnz fdos_expand22 ; make sure it's a valid drive 0 00007ADC E98500 jmp fdos_expand50 2317 <1> fdos_expand22: 0 00007ADF 16 push ss 0 00007AE0 07 pop es 0 00007AE1 BF[0000] mov di,offset pri_pathname ; build name in pathname buffer 0 00007AE4 C536[6000] lds si,[fdos_pb+2] 2322 <1> 2323 <1> ; we must trick redir_build_path to find the correct function number - 2324 <1> ; otherwise we could not get correct (critical) error reporting to work 0 00007AE8 55 push bp 0 00007AE9 BD[6400] mov bp,offset fdos_pb+6 0 00007AEC 896E02 mov [2 + bp],bp 0 00007AEF C6460055 mov byte ptr [bp],FD_EXPAND 2329 <1> 0 00007AF3 E8[0000] call redir_build_path ; build name from LDT 0 00007AF6 5D pop bp 0 00007AF7 726E jc fdos_expand60 ; bail out if bad name 2333 <1> 0 00007AF9 36C53E[0000] lds di,[ss:current_ldt] 0 00007AFE F7454300C0 test word [LDT_FLAGS + di],LFLG_NETWRKD+LFLG_PHYSICAL 0 00007B03 742D jz fdos_expand25 0 00007B05 F745430010 test word [LDT_FLAGS + di],LFLG_SUBST 0 00007B0A 7526 jnz fdos_expand25 0 00007B0C 8B5D4F mov bx,[LDT_ROOTLEN + di] 0 00007B0F 83FB02 cmp bx,2 0 00007B12 761E jbe fdos_expand25 0 00007B14 BE[0000] mov si,offset pri_pathname 0 00007B17 8A4502 mov al,[LDT_NAME+2 + di] 0 00007B1A 368804 mov [ss:si],al 0 00007B1D 36C744013A5C mov word ptr [ss:1 + si],':\' ; NASM port swapped text literals 0 00007B23 46 inc si 0 00007B24 46 inc si 0 00007B25 4B dec bx 0 00007B26 4B dec bx 2350 <1> fdos_expand23: 0 00007B27 46 inc si 0 00007B28 368A00 mov al,[ss:si+bx] 0 00007B2B 368804 mov [ss:si],al 0 00007B2E 3C00 cmp al,0 0 00007B30 75F5 jne fdos_expand23 2356 <1> fdos_expand25: 2357 <1> 0 00007B32 36C53E[0000] lds di,[ss:current_ldt] ; we need to append a '\' if 0 00007B37 8B5D4F mov bx,[LDT_ROOTLEN + di] ; we are at the root 0 00007B3A F745430010 test word [LDT_FLAGS + di],LFLG_SUBST 0 00007B3F 7403 jz fdos_expand30 ; if drive is SUBST'd then 0 00007B41 BB0200 mov bx,2 ; only append if real root 2363 <1> fdos_expand30: 0 00007B44 BE[0000] mov si,offset pri_pathname ; SS:SI -> full path 0 00007B47 16 push ss 0 00007B48 1F pop ds ; leave current ldt -> buffer as LAN 0 00007B49 8936[0000] mov word ptr [current_ldt],si ; MAN 2.1 extended edition expects it 0 00007B4D 8C1E[0200] mov word ptr [current_ldt+2],ds 0 00007B51 B85C00 mov ax,'\' ; get pathchar in AX for checks 0 00007B54 3820 cmp byte ptr [si+bx],ah ; are we at the root ? 0 00007B56 7502 jne fdos_expand40 ; if so append a '\' 0 00007B58 8900 mov word ptr [si+bx],ax 2373 <1> fdos_expand40: 0 00007B5A 36C43E[6800] les di,[ss:fdos_pb+10]; ES:DI -> destination buffer 0 00007B5F E8AA0D call copy_asciiz ; copy the full pathname 0 00007B62 1F pop ds 0 00007B63 C3 ret 2378 <1> 2379 <1> fdos_expand50: 0 00007B64 BBF1FF mov bx,ED_DRIVE ; return bad drive error 2381 <1> fdos_expand60: 0 00007B67 89D8 mov ax,bx 0 00007B69 1F pop ds 0 00007B6A E9B9F2 jmp fdos_error 2385 <1> 2386 <1> expand_dev: 2387 <1> ;---------- 0 00007B6D C436[6000] les si,[fdos_pb+2] ; this is the original source 0 00007B71 26AD es lodsw ; get the source 0 00007B73 C43E[6800] les di,[fdos_pb+10] ; data will end up here 0 00007B77 80FC3A cmp ah,':' ; is a drive specified ? 0 00007B7A 7407 je expand_dev10 0 00007B7C B041 mov al,'A' 0 00007B7E 360206[0000] add al,[ss:current_dsk] 2395 <1> expand_dev10: 0 00007B83 E88B09 call toupper ; make sure drive letter is upper case 0 00007B86 AA stosb ; plant an 'd' 0 00007B87 B83A2F mov ax,':'+256*'/' 0 00007B8A AB stosw ; make that 'd:/' 0 00007B8B BB[0000] mov bx,offset name_buf ; DS:BX -> name buffer 0 00007B8E E95507 jmp unparse ; unparse the device name 2402 <1> 2403 <1> 2404 <1> ; RENAME FILE 2405 <1> 2406 <1> ; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+ 2407 <1> ; | 56 | old name | | new name | 2408 <1> ; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+ 2409 <1> 2410 <1> ; entry: 2411 <1> ; ------ 2412 <1> ; old name: segmented address of ASCIIZ name 2413 <1> ; new name: segmented address of ASCIIZ name 2414 <1> 2415 <1> ; exit: 2416 <1> ; ----- 2417 <1> ; AX: 0000 or error code ( < 0) 2418 <1> 2419 <1> ; Note: R/O files can be renamed. 2420 <1> ; --- 2421 <1> 2422 <1> fdos_move: 2423 <1> ;--------- 0 00007B91 E8[0000] call redir_move_offer 0 00007B94 E838F2 call local_disk ; get MXdisk, switch stack 0 00007B97 E84E03 call path_prep ; parse the path, go to bottom level 0 00007B9A E86F05 call chk_no_dev 0 00007B9D 36833E[0000]00 cmp word [ss:remote_call],0 ; wildcards allowed if server/FCB 0 00007BA3 7503 jnz move10 0 00007BA5 E80608 call chk_no_wild ; make sure not a wild card 2431 <1> move10: 0 00007BA8 E8[0000] call finddfcbf ; else try to locate directory entry 0 00007BAB 7445 jz fdos_ED_FILE ; error if no match occurred 2434 <1> move20: 0 00007BAD E8790C call close_if_same_psp ; make sure not open by other PDs 2436 <1> %ifdef PASSWORD 0 00007BB0 E82C0F call check_pwd_any ; check if password protected 2438 <1> %endif 0 00007BB3 8B36[0000] mov si,[dirp] ; get matching directory entry 0 00007BB7 BF[3400] mov di,offset save_area ; get a temporary save area 0 00007BBA B91000 mov cx,32/2 ; save it all 0 00007BBD F3A5 rep movsw ; so we can move it to new entry 2443 <1> 0 00007BBF BE[0C00] mov si,offset fdos_hds 0 00007BC2 BF[1500] mov di,offset saved_hds 0 00007BC5 B109 mov cl,HDS_LEN 0 00007BC7 F3A4 rep movsb ; copy current HDS to safe place 2448 <1> 0 00007BC9 A1[0000] mov ax,[dcnt] ; also save directory index 0 00007BCC A3[1E00] mov [saved_dcnt],ax ; so we can release entry later 2451 <1> 0 00007BCF C43E[6800] les di,[fdos_pb+10] ; es:di -> path name 0 00007BD3 E81603 call path_prep_ptr ; find the destination path 0 00007BD6 E83305 call chk_no_dev ; no devices allowed here 0 00007BD9 36833E[0000]00 cmp word [ss:remote_call],0 ; wildcards allowed if server/FCB 0 00007BDF 7503 jnz move25 0 00007BE1 E8CA07 call chk_no_wild ; make sure not a wild card 2458 <1> move25: 0 00007BE4 A0[1400] mov al,[fdos_hds_drv] ; get the work drive 0 00007BE7 3A06[1D00] cmp al,[saved_hds_drv] ; make sure same drive for 0 00007BEB 740B je move30 ; source and destination 2462 <1> 0 00007BED B8EFFF mov ax,ED_DEVICE ; "not same device" error 0 00007BF0 EB03 jmp fdos_moverr ; return the error 2465 <1> fdos_ED_FILE: 0 00007BF2 B8FEFF mov ax,ED_FILE ; get error code 2467 <1> fdos_moverr: 0 00007BF5 E92EF2 jmp fdos_error ; return the error 2469 <1> 2470 <1> move30: ; same drive for source & destination 0 00007BF8 A0[6600] mov al,byte ptr [fdos_pb+8] ; check attributes 2472 <1> %ifdef PASSWORD 0 00007BFB 833E[0000]00 cmp word [dosfat],FAT32 ; FAT32 filesystem? 0 00007C00 7411 je move31 ; yes, then ignore passwords 0 00007C02 803E[4200]00 cmp byte [save_area+DPWD],0 0 00007C07 740A je move31 0 00007C09 F706[4800]FF0F test word [save_area+DPWM],0fffh ; no access rights set? 0 00007C0F 7402 jz move31 ; then assume it is unprotected 0 00007C11 0C02 or al,DA_HIDDEN 2480 <1> move31: 2481 <1> %endif 0 00007C13 F6D0 not al 0 00007C15 241E and al,DA_HIDDEN+DA_SYSTEM+DA_DIR+DA_VOLUME 0 00007C17 8406[3F00] test [save_area+DATTS],al 0 00007C1B 757E jnz move80 0 00007C1D BE[2900] mov si,offset info_fcb+1 ; SI->new name (possible wildcards) 0 00007C20 89F7 mov di,si ; DI->new name 0 00007C22 BB[3400] mov bx,offset save_area ; current name on disk 0 00007C25 803F2E cmp byte ptr [DNAME + bx],'.' 0 00007C28 7471 je move80 0 00007C2A B90B00 mov cx,11 2492 <1> move40: ; fill in the wild card characters 0 00007C2D AC lodsb ; get next character from new name 2494 <1> %ifdef KANJI 0 00007C2E E88E01 call dbcs_lead ; is it the 1st of a kanji pair 0 00007C31 7508 jne move45 0 00007C33 49 dec cx ; copied this one 0 00007C34 E312 jcxz move55 ; discard if no room for kanji char 0 00007C36 AA stosb ; copy 1st byte of Kanji pair 0 00007C37 43 inc bx 0 00007C38 AC lodsb ; copy 2nd byte 0 00007C39 EB09 jmp move50 2503 <1> move45: 2504 <1> %endif 0 00007C3B E8D308 call toupper ; make it upper case 0 00007C3E 3C3F cmp al,'?' ; is it just a wild card? 0 00007C40 7502 jne move50 ; no, put in destination as is 0 00007C42 8A07 mov al,[bx] ; else leave original character 2509 <1> move50: ; AL = next char for destination 0 00007C44 AA stosb ; store next char in destination 0 00007C45 43 inc bx ; increment all pointers 0 00007C46 E2E5 loop move40 ; repeat for all 11 characters 2513 <1> move55: 2514 <1> 0 00007C48 E8[0000] call finddfcbf ; find first non-volume entry 0 00007C4B 7571 jnz move_access ; file already exists, return error 2517 <1> 0 00007C4D E8A900 call move_comp ; source & destination in same dir? 0 00007C50 7505 jne move60 ; skip if moving to different directory 0 00007C52 E88E00 call move_seek ; else find old entry again 0 00007C55 EB0A jmp move70 ; replace name in old entry 2522 <1> 2523 <1> move60: ; moving to different directory 0 00007C57 F606[3F00]10 test byte [save_area+DATTS],DA_DIR ; can't move directory to new path 0 00007C5C 7560 jnz move_access ; so return error if new path 0 00007C5E E8[0000] call allocdir ; allocate a directory entry 2527 <1> move70: 0 00007C61 E8[0000] call del_lfn ; make sure no LFN is before it 0 00007C64 BE[2900] mov si,offset info_fcb+1 ; get pointer to new name 0 00007C67 8B3E[0000] mov di,[dirp] ; get pointer to directory entry 0 00007C6B B90B00 mov cx,11 ; copy new name into buffer 0 00007C6E F3A4 rep movsb 2533 <1> 2534 <1> 0 00007C70 BE[3F00] mov si,offset save_area+11 ; copy remaining info 0 00007C73 B91500 mov cx,32-11 0 00007C76 F3A4 rep movsb 0 00007C78 E8[0000] call update_dir ; update the disk 2539 <1> 0 00007C7B E87B00 call move_comp ; did we rename across directories? 0 00007C7E 741B je move80 ; skip if in same directory 0 00007C80 BE[1500] mov si,offset saved_hds 0 00007C83 BF[0C00] mov di,offset fdos_hds ; else need to copy HDS back 0 00007C86 B90900 mov cx,HDS_LEN ; so we can get old entry again 0 00007C89 F3A4 rep movsb ; (time to get rid of it) 0 00007C8B E85500 call move_seek ; seek the original entry 0 00007C8E E8[0000] call del_lfn ; and delete LFN if one exists 0 00007C91 8B1E[0000] mov bx,[dirp] 0 00007C95 C607E5 mov byte [DNAME + bx],0E5h ; and bye, bye! it goes... 0 00007C98 E8[0000] call update_dir ; update the old directory entry 2551 <1> move80: 0 00007C9B 36833E[0000]00 cmp word [ss:remote_call],0 ; wildcards allowed if server/FCB 0 00007CA1 741E jz move90 ; so check for multiple files 0 00007CA3 E84202 call path_prep ; parse the path, go to bottom level 2555 <1> 0 00007CA6 A1[1E00] mov ax,[saved_dcnt] ; restore dcnt for remote call 0 00007CA9 A3[0000] mov [dcnt],ax ; to function properly 0 00007CAC 8326[0000]00 and word [chdblk],0 0 00007CB1 8326[0200]00 and word [chdblk+2],0 2560 <1> 0 00007CB6 E8[0000] call finddfcb ; try to locate another directory entry 0 00007CB9 7406 jz move90 ; no, return now 0 00007CBB E9EFFE jmp move20 ; round again if we do 2564 <1> 2565 <1> move_access: 0 00007CBE E99EF1 jmp fdos_ED_ACCESS ; "access denied" if file 2567 <1> ; already exists 2568 <1> move90: 2569 <1> ; in order to update the current directory in case part of it has been 2570 <1> ; renamed we call fdos_chdir which does all the work for rebuilding 2571 <1> ; the LDT_ for the given drive 0 00007CC1 16 push ss 0 00007CC2 1F pop ds 0 00007CC3 BB[0000] mov bx,offset sec_pathname 0 00007CC6 A1[0A00] mov ax,[path_drive] 0 00007CC9 05413A add ax,'A'+(':'*100h) 0 00007CCC 8907 mov [bx],ax 0 00007CCE C747022E00 mov word ptr [2 + bx],'.' 0 00007CD3 8C1E[6200] mov [fdos_pb+4],ds 0 00007CD7 891E[6000] mov [fdos_pb+2],bx 0 00007CDB C606[0000]00 mov byte [remote_call],0 0 00007CE0 E93CF2 jmp fdos_move_chdir 2583 <1> 2584 <1> move_seek: ; re-seek the old directory entry 0 00007CE3 A1[1E00] mov ax,[saved_dcnt] ; get saved directory count 0 00007CE6 48 dec ax ; move back one for GETDIR 0 00007CE7 A3[0000] mov [dcnt],ax ; set search offset 0 00007CEA 8326[0000]00 and word [chdblk],0 ; follow the chains, not sequential 0 00007CEF 8326[0200]00 and word [chdblk+2],0 0 00007CF4 B100 mov cl,0 ; return next entry 0 00007CF6 E9[0000] jmp getdir ; in current directory 2592 <1> 2593 <1> move_comp: 0 00007CF9 A1[0C00] mov ax,[fdos_hds_blk] 0 00007CFC 8B16[0E00] mov dx,[fdos_hds_blk+2] 0 00007D00 3B06[1500] cmp ax,[saved_hds_blk] 0 00007D04 7504 jne move_comp10 0 00007D06 3B16[1700] cmp dx,[saved_hds_blk+2] 2599 <1> move_comp10: 0 00007D0A C3 ret 2601 <1> 2602 <1> 2603 <1> ; GET/SET FILE DATE/TIME 2604 <1> 2605 <1> ; +----+----+----+----+----+----+----+----+----+----+ 2606 <1> ; | 57 | handle | mode | date | time | 2607 <1> ; +----+----+----+----+----+----+----+----+----+----+ 2608 <1> 2609 <1> ; entry: 2610 <1> ; ------ 2611 <1> ; handle: open file handle 2612 <1> ; mode: 0 = get date/time, 1 = set date/time 2613 <1> ; date: date as in directory FCB 2614 <1> ; time: time as in directory FCB 2615 <1> 2616 <1> ; exit: 2617 <1> ; ----- 2618 <1> ; AX: 0000 or error code ( < 0) 2619 <1> ; date: date of last modification if mode = 0 2620 <1> ; time: date of last modification if mode = 0 2621 <1> 2622 <1> fdos_dattim: 2623 <1> ;----------- 0 00007D0B E85E0A call vfy_dhndl_ptr ; check file handle # 0 00007D0E E8[0000] call redir_dhndl_offer 0 00007D11 E8BBF0 call local_disk ; get MXdisk, switch stack 0 00007D14 E82D0A call check_handle ; check if legal file handle 0 00007D17 833E[6200]00 cmp word [fdos_pb+4],0 ; get/set date/time? 0 00007D1C 750F jne dattim1 0 00007D1E 268B470F mov ax,[es:DHNDL_DATE + bx] ; get date 0 00007D22 A3[6400] mov [fdos_pb+6],ax 0 00007D25 268B470D mov ax,[es:DHNDL_TIME + bx] ; get time 0 00007D29 A3[6600] mov [fdos_pb+8],ax 0 00007D2C C3 ret 2635 <1> dattim1: ; else set date/time stamp 0 00007D2D 8B16[6400] mov dx,[fdos_pb+6] ; set date 0 00007D31 A1[6600] mov ax,[fdos_pb+8] ; and time 0 00007D34 EB07 jmp set_timestamp 2639 <1> 2640 <1> Public timestamp_dhndl 2641 <1> 2642 <1> timestamp_dhndl: 2643 <1> ;--------------- 2644 <1> ; On Entry: 2645 <1> ; ES:BX -> DHNDL_ 2646 <1> ; On Exit: 2647 <1> ; ES:BX preserved 2648 <1> ; 2649 <1> ; Mark this DHNDL_ with the current time and date 0 00007D36 06 push es 0 00007D37 53 push bx 0 00007D38 E83D0D call ReadTOD ; get TOD in DX/AX 0 00007D3B 5B pop bx 0 00007D3C 07 pop es 2655 <1> ; jmp set_timestamp 2656 <1> 2657 <1> set_timestamp: 2658 <1> ;------------- 2659 <1> ; On Entry: 2660 <1> ; ES:BX -> DHNDL_ 2661 <1> ; AX = time 2662 <1> ; DX = date 2663 <1> ; On Exit: 2664 <1> ; None 2665 <1> ; 0 00007D3D 26806705BF and byte [es:DHNDL_ATTR + bx],~ DHAT_CLEAN 0 00007D42 2689570F mov [es:DHNDL_DATE + bx],dx ; remember to update directory 0 00007D46 2689470D mov [es:DHNDL_TIME + bx],ax ; ask SHARE to record the changes 0 00007D4A FF1E[0800] call far [share_stub+S_RECORD] ; for the benefit of others 0 00007D4E C3 ret 2671 <1> 2672 <1> 2673 <1> fdos_reopen_fcb: 2674 <1> ;--------------- 2675 <1> ; On entry 2676 <1> ; On exit on success pb offset 6 set to 0 if device, 1 if disk file 0 00007D4F F606[0100]80 test byte [remote_call+1],DHM_FCB/100h 0 00007D54 7506 jnz fcb_reopen0 0 00007D56 B8FFFF mov ax,ED_FUNCTION 0 00007D59 E9CAF0 jmp fdos_error 2681 <1> fcb_reopen0: 0 00007D5C E870F0 call local_disk 0 00007D5F E88601 call path_prep 0 00007D62 7230 jc fcb_reopen_error ; any error means reopen is invalid 0 00007D64 E8B003 call check_device 0 00007D67 732B jnc fcb_reopen_error ; we should not find devices here 0 00007D69 A1[6400] mov ax,[fdos_pb+6] 0 00007D6C A3[0C00] mov [fdos_hds_blk],ax 0 00007D6F C706[0E00]0000 mov word [fdos_hds_blk+2],0 0 00007D75 A1[6600] mov ax,[fdos_pb+8] 0 00007D78 48 dec ax 0 00007D79 A3[0000] mov [dcnt],ax 0 00007D7C 31C9 xor cx,cx 0 00007D7E 890E[0000] mov [chdblk],cx 0 00007D82 890E[0200] mov [chdblk+2],cx 0 00007D86 E8[0000] call getdir 0 00007D89 7409 jz fcb_reopen_error 0 00007D8B 803FE5 cmp byte [DNAME + bx],0e5h ; has the entry been deleted ? 0 00007D8E 7404 je fcb_reopen_error 0 00007D90 A3[6000] mov [fdos_pb+2],ax 0 00007D93 C3 ret 2702 <1> fcb_reopen_error: 0 00007D94 B8DDFF mov ax,ED_NOFCBS 0 00007D97 E98CF0 jmp fdos_error 2705 <1> 2706 <1> BDOS_CODE ends 442 ;=== Pop trace listing source 443 ;=== Push trace listing source: drdos/utils.nas 444 %include "utils.nas" 1 <1> ; File : $UTILS.FDO$ 2 <1> ; 3 <1> ; Description : 4 <1> ; 5 <1> ; Original Author : DIGITAL RESEARCH 6 <1> ; 7 <1> ; Last Edited By : $CALDERA$ 8 <1> ; 9 <1> ;-----------------------------------------------------------------------; 10 <1> ; Copyright Work of Caldera, Inc. All Rights Reserved. 11 <1> ; 12 <1> ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, 13 <1> ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. 14 <1> ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES 15 <1> ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF 16 <1> ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO 17 <1> ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE 18 <1> ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE 19 <1> ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, 20 <1> ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, 21 <1> ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, 22 <1> ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF 23 <1> ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT 24 <1> ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND 25 <1> ; CIVIL LIABILITY. 26 <1> ;-----------------------------------------------------------------------; 27 <1> ; 28 <1> ; *** Current Edit History *** 29 <1> ; *** End of Current Edit History *** 30 <1> ; 31 <1> ; $Log$ 32 <1> ; UTILS.FDO 1.39 94/11/30 13:39:18 33 <1> ; added share_delay function 34 <1> ; UTILS.FDO 1.37 94/07/13 15:42:01 35 <1> ; Change to rename/delete of file open in compatibility modes 36 <1> ; UTILS.FDO 1.36 94/06/28 11:10:10 37 <1> ; Limit ddsc allocation to 1st 255 38 <1> ; UTILS.FDO 1.34 94/04/25 19:33:04 39 <1> ; Reject blank names (ie. all spaces) when parsing path 40 <1> ; We used to die in rebuild_ldt_curdir (GATEWAY problem) 41 <1> ; UTILS.FDO 1.33 93/12/16 13:57:06 42 <1> ; Fix path_prep bug when dir in path doesn't exist 43 <1> ; UTILS.FDO 1.32 93/12/09 23:56:10 44 <1> ; Move non-inherited bit to correct place in file handle 45 <1> ; UTILS.FDO 1.31 93/12/08 03:30:03 46 <1> ; Add extra check to offer_join: consider JOIN B: \FRED, SUBST L: \FRED\FRED 47 <1> ; A CD L:\ would see FRED at the root of B: and change into it, so we 48 <1> ; would end up at \FRED, so we only check if ROOTLEN=2 49 <1> ; UTILS.FDO 1.27 93/11/19 17:45:14 50 <1> ; Fix for SERVER print queue viewing problem 51 <1> ; UTILS.FDO 1.26 93/11/08 16:30:12 52 <1> ; Get dat/time on device handle returns current date/time 53 <1> ; UTILS.FDO 1.25 93/09/14 20:03:42 54 <1> ; Trust LFLG_PHYSICAL 55 <1> ; UTILS.FDO 1.23 93/09/03 20:26:09 56 <1> ; Add "no critical errors" support (int 21/6C) 57 <1> ; UTILS.FDO 1.22 93/07/26 18:11:00 58 <1> ; re-arrange DHNDL_DCNTHI for the benefit of Geoworks 59 <1> ; UTILS.FDO 1.21 93/07/20 22:43:48 60 <1> ; Even fewer checks on int 25/26 61 <1> ; ENDLOG 62 <1> ; General utility include module for FDOS.A86 63 <1> 64 <1> === Switch to base=00C180h -> "BDOS_DATA" 65 <1> section BDOS_DATA public align=2 class=DATA 65 ****************** <1> warning: segment attributes specified on redeclaration of segment: ignoring [-w+other] 66 <1> 0 0000194E 643A5C66696C656E61 join_name db 'd:\filename.ext',0 0 00001957 6D652E65787400 68 <1> 69 <1> BDOS_DATA ends 70 <1> 71 <1> === Switch to base=000000h -> "BDOS_CODE" 72 <1> section BDOS_CODE public align=1 class=CODE 72 ****************** <1> warning: segment attributes specified on redeclaration of segment: ignoring [-w+other] 73 <1> 74 <1> select_pb2: 75 <1> ;---------- 0 00007D9A E8AC03 call get_pb2_drive ; get drive from parameter block 77 <1> ; jmp select_unique ; select drive, make HDS unique 78 <1> 79 <1> select_unique: 80 <1> ;------------- 81 <1> ; entry: AL = drive to select (0-15) 82 <1> 0 00007D9D A2[0A00] mov byte ptr [path_drive],al ; save logical drive 0 00007DA0 E9[0000] jmp select_logical_drv ; select the drive 85 <1> 86 <1> 87 <1> logical2physical: 88 <1> ;---------------- 89 <1> ; On Entry: 90 <1> ; AL = drive to select 91 <1> ; On Exit: 92 <1> ; AL = appropriate physical drive to select 93 <1> ; 94 <1> ; This routine is called by low level routines (func_ddio, func_getdpb) 95 <1> ; and bypasses the checks for networked/joined drives together with the 96 <1> ; normal media change checks. It does however handle SUBST'd drives. 97 <1> ; 0 00007DA3 E8[0000] call get_ldt_raw ; ES:BX -> LDT for our drive 0 00007DA6 7216 jc logical2physical10 ; if we don't have one must be physical 0 00007DA8 26F747430020 test word [es:LDT_FLAGS + bx],LFLG_JOINED 0 00007DAE 750E jnz logical2physical10 ; joined drive - treat as physical 0 00007DB0 26F747430010 test word [es:LDT_FLAGS + bx],LFLG_SUBST 0 00007DB6 7406 jz logical2physical10 ; as long as we aren't SUBST'd it OK 0 00007DB8 268A07 mov al,[es:LDT_NAME + bx] ; get the drive from the ascii name 0 00007DBB 241F and al,1fh ; as the drive may require rebuilding 0 00007DBD 48 dec ax ; make it zero based 107 <1> logical2physical10: 0 00007DBE C3 ret 109 <1> 110 <1> 111 <1> Public dbcs_lead 112 <1> 113 <1> dbcs_lead: 114 <1> ;--------- 115 <1> ; Return true if given byte is the first of a double byte character. 116 <1> ; Entry 117 <1> ; al = byte to be tested 118 <1> ; Exit 119 <1> ; Z Flag = 1 - byte is a DBCS lead 120 <1> ; 0 - byte is not a DBCS lead 121 <1> ; Lost 122 <1> ; no registers changed 123 <1> 124 <1> %ifdef KANJI 0 00007DBF 56 push si 0 00007DC0 53 push bx 0 00007DC1 50 push ax 128 <1> 129 <1> ; First get a pointer to the double byte lead table in the COUNTRY info. 0 00007DC2 BE[0200] mov si, offset DBCS_tbl+2 ; ds:si -> double byte table 131 <1> 132 <1> ; Examine each entry in the table to see if it defines a range that includes 133 <1> ; the given character. 0 00007DC5 88C3 mov bl, al ; bl = byte to be tested 135 <1> dbcs_loop: 0 00007DC7 36AD ss lodsw ; al/ah = start/end of range 0 00007DC9 85C0 test ax, ax ; end of table? 0 00007DCB 740C jz dbcs_no ; yes - exit (not in table) 0 00007DCD 38D8 cmp al, bl ; start <= bl? 0 00007DCF 77F6 ja dbcs_loop ; no - try next range 0 00007DD1 38DC cmp ah, bl ; bl <= end? 0 00007DD3 72F2 jb dbcs_loop ; no - try next range 143 <1> 0 00007DD5 38C0 cmp al, al ; return with Z flag set 0 00007DD7 EB02 jmp dbcs_exit 146 <1> dbcs_no: 0 00007DD9 3C01 cmp al, 1 ; return with Z flag reset 148 <1> 149 <1> dbcs_exit: 0 00007DDB 58 pop ax 0 00007DDC 5B pop bx 0 00007DDD 5E pop si 0 00007DDE C3 ret 154 <1> %else 155 <1> test al, al ; force non-0 condition 156 <1> ret 157 <1> %endif 158 <1> 159 <1> 160 <1> kanji_eos: 161 <1> ;--------- 162 <1> ; entry: ES:DI -> string to find the end of 163 <1> ; exit: ES:DI -> character before NUL byte 164 <1> 0 00007DDF 89FA mov dx,di ; in case string is empty 166 <1> kanji_eos1: 0 00007DE1 268A05 mov al,[es:di] ; get next character 0 00007DE4 84C0 test al,al ; is it the final NUL byte 0 00007DE6 740B jz kanji_eos9 ; return if NUL found 0 00007DE8 89FA mov dx,di 0 00007DEA 47 inc di ; move to next character 172 <1> %ifdef KANJI 0 00007DEB E8D1FF call dbcs_lead ; is this first half of 16-bit char? 0 00007DEE 75F1 jne kanji_eos1 ; skip if normal character 0 00007DF0 47 inc di ; else skip 2nd half (should really check) 176 <1> %endif 0 00007DF1 EBEE jmp kanji_eos1 ; loop back for next character 178 <1> 179 <1> kanji_eos9: 0 00007DF3 89D7 mov di,dx ; ES:DI -> last character 0 00007DF5 C3 ret ; end of string found 182 <1> 183 <1> 184 <1> path_chop: 185 <1> ;--------- 186 <1> ; entry: ES:DI -> path = "d:\level1\level2\" 187 <1> ; exit: path = "d:\level1\" 188 <1> 0 00007DF6 268A05 mov al,[es:di] ; get next character 0 00007DF9 84C0 test al,al ; end of string? 0 00007DFB 7414 jz path_chop2 ; yes, string scanned 0 00007DFD 47 inc di ; next character 193 <1> %ifdef KANJI 0 00007DFE E8BEFF call dbcs_lead ; lead-in of 16-bit character? 0 00007E01 7503 jne path_chop1 ; no, normal 8-bit 0 00007E03 47 inc di ; skip hi-byte (should really check) 0 00007E04 EBF0 jmp path_chop ; try again 198 <1> path_chop1: 199 <1> %endif 0 00007E06 E80007 call check_slash ; is this a path character 0 00007E09 75EB jne path_chop ; loop back if not path character 0 00007E0B 89CA mov dx,cx ; last but one '/' = last '/' 0 00007E0D 89F9 mov cx,di ; last '/' = current '/' 0 00007E0F EBE5 jmp path_chop ; repeat 205 <1> path_chop2: 0 00007E11 89D7 mov di,dx ; ES:DI -> last but one slash + 1 0 00007E13 29C0 sub ax,ax ; get a NUL byte 0 00007E15 AA stosb ; chop off the last level 0 00007E16 C3 ret 210 <1> 211 <1> Public rebuild_ldt_root 212 <1> 213 <1> rebuild_ldt_root: 214 <1> ;---------------- 215 <1> ; On Entry: 216 <1> ; ES:BX -> LDT_ to rebuild 217 <1> ; fdos_hds = physical root for this drive 218 <1> ; On Exit: 219 <1> ; ES:BX preserved 220 <1> ; LDT_ROOT rebuilt from ASCII LDT_NAME 221 <1> ; 0 00007E17 1E push ds 0 00007E18 06 push es 0 00007E19 1F pop ds ; DS:BX -> LDT_ 0 00007E1A 16 push ss 0 00007E1B 07 pop es 0 00007E1C BF[0000] mov di,offset temp_ldt ; ES:DI -> temp LDT_ 0 00007E1F 8D7703 lea si,[LDT_NAME+3 + bx] ; point to start of pathname 0 00007E22 8B4F4F mov cx,[LDT_ROOTLEN + bx] ; CX = end of root portion 0 00007E25 31C0 xor ax,ax ; assume we want root block 0 00007E27 83E903 sub cx,3 ; skip the 'D:\' 0 00007E2A 7611 jbe rebuild_ldt_root10 ; nothing to do unless SUBST'd 0 00007E2C F3A4 rep movsb ; copy the root portion of the name 0 00007E2E E87200 call select_dir ; select this directory 0 00007E31 730A jnc rebuild_ldt_root10 0 00007E33 31C0 xor ax,ax 0 00007E35 C7474F0200 mov word [LDT_ROOTLEN + bx],2 ; force ourselves into the root 0 00007E3A 884703 mov [LDT_NAME+3 + bx],al ; as the media has changed 239 <1> rebuild_ldt_root10: 0 00007E3D 1E push ds 0 00007E3E 07 pop es ; ES:BX -> LDT_ 0 00007E3F 1F pop ds 0 00007E40 A1[0C00] mov ax,[fdos_hds_blk] 0 00007E43 8B16[0E00] mov dx,[fdos_hds_blk+2] 0 00007E47 2689474B mov [es:LDT_ROOT + bx],ax ; update our root block 0 00007E4B 26895753 mov [es:LDT_ROOTH + bx],dx 247 <1> %ifdef JOIN 0 00007E4F A0[1400] mov al,[fdos_hds_drv] ; and the physical drive 0 00007E52 2688474D mov [es:LDT_DRV + bx],al 250 <1> %endif 0 00007E56 C3 ret 252 <1> 253 <1> 254 <1> rebuild_ldt_curdir: 255 <1> ;------------------ 256 <1> ; On Entry: 257 <1> ; ES:BX -> LDT_ to rebuild 258 <1> ; fdos_hds = logical root of this drive 259 <1> ; On Exit: 260 <1> ; ES:BX preserved 261 <1> ; LDT_DRV and LDT_BLK rebuilt from ASCII LDT_NAME 262 <1> ; 0 00007E57 1E push ds 0 00007E58 06 push es 0 00007E59 1F pop ds ; DS:BX -> LDT_ 0 00007E5A 16 push ss 0 00007E5B 07 pop es 0 00007E5C BF[0000] mov di,offset temp_ldt ; ES:DI -> temp LDT_ 0 00007E5F 8B774F mov si,[LDT_ROOTLEN + bx] ; SI = end of root portion 0 00007E62 8D30 lea si,[LDT_NAME + bx+si] ; point to subdir entry 0 00007E64 AC lodsb ; get 1st char 0 00007E65 E8A106 call check_slash ; is it a leading '\' ? 0 00007E68 7401 je rebuild_ldt_curdir10 ; yes, discard it 0 00007E6A 4E dec si ; else leave it alone 275 <1> rebuild_ldt_curdir10: 0 00007E6B 84C0 test al,al ; anything to do? 0 00007E6D 741A jz rebuild_ldt_curdir40 ; no, we are already there 278 <1> rebuild_ldt_curdir20: 0 00007E6F AC lodsb 0 00007E70 AA stosb ; copy the string 0 00007E71 84C0 test al,al ; until we hit the terminating NUL 0 00007E73 75FA jnz rebuild_ldt_curdir20 0 00007E75 4F dec di 0 00007E76 E82A00 call select_dir ; select this directory 0 00007E79 730E jnc rebuild_ldt_curdir40 0 00007E7B 8B774F mov si,[LDT_ROOTLEN + bx] ; SI = end of root portion 0 00007E7E 83FE03 cmp si,3 ; is root real root or a subdir ? 0 00007E81 7703 ja rebuild_ldt_curdir30 0 00007E83 BE0300 mov si,3 ; real root, leave '\' alone 290 <1> rebuild_ldt_curdir30: 0 00007E86 C60000 mov byte [LDT_NAME + bx+si],0 ; move ASCII to root 292 <1> rebuild_ldt_curdir40: 0 00007E89 1E push ds 0 00007E8A 07 pop es ; ES:BX -> LDT_ 0 00007E8B 1F pop ds 0 00007E8C A1[0C00] mov ax,[fdos_hds_blk] 0 00007E8F 8B16[0E00] mov dx,[fdos_hds_blk+2] 0 00007E93 26894749 mov [es:LDT_BLK + bx],ax ; update our curdir block 0 00007E97 26895751 mov [es:LDT_BLKH + bx],dx 300 <1> %ifdef JOIN 0 00007E9B A0[1400] mov al,[fdos_hds_drv] ; and the physical drive 0 00007E9E 2688474D mov [es:LDT_DRV + bx],al 303 <1> %endif 0 00007EA2 C3 ret 305 <1> 306 <1> select_dir: 307 <1> ;---------- 308 <1> ; On Entry: 309 <1> ; DS:BX -> LDT 310 <1> ; ES:DI -> end of ASCII path 311 <1> ; temp_ldt contains dir to select 312 <1> ; On Exit: 313 <1> ; DS:BX preserved 314 <1> ; CY set on error, root of original drive reselected 315 <1> ; 0 00007EA3 B85C2E mov ax,'\.' ; append a "\." in case it's the root ; NASM port swapped text literals 0 00007EA6 AB stosw ; (and so a NULL path) 0 00007EA7 31C0 xor ax,ax 0 00007EA9 AA stosb 0 00007EAA 1E push ds 0 00007EAB 53 push bx ; make sure LDT survives 0 00007EAC 16 push ss 0 00007EAD 1F pop ds ; DS back to SYSDAT 0 00007EAE BE[0000] mov si,offset temp_ldt ; ES:SI -> directory to select 0 00007EB1 E8A700 call path_prep_next ; try to move into it 326 <1> %ifdef JOIN 0 00007EB4 E8B30A call offer_join ; are we opening a JOIN'd drive ? 0 00007EB7 732C jnc select_dir20 329 <1> %endif 0 00007EB9 E8[0000] call finddfcbf ; find the directory entry 0 00007EBC 7418 jz select_dir10 ; stop if we can't 0 00007EBE F6470B10 test byte [DATTS + bx],DA_DIR ; check if directory 0 00007EC2 7412 jz select_dir10 ; fail if this is a file 0 00007EC4 1E push ds 0 00007EC5 07 pop es 0 00007EC6 8D3F lea di,[DNAME + bx] ; ES:DI -> ASCII name to open 0 00007EC8 B90B00 mov cx,8+3 0 00007ECB B020 mov al,' ' 0 00007ECD F3AE repe scasb ; is it all spaces ? 0 00007ECF 7405 je select_dir10 ; if so reject it 0 00007ED1 E8A403 call open_dir 0 00007ED4 730F jnc select_dir20 343 <1> select_dir10: 0 00007ED6 A1[1000] mov ax,[fdos_hds_root] ; move to the virtual root 0 00007ED9 8B16[1000] mov dx,[fdos_hds_root] 0 00007EDD A3[0C00] mov [fdos_hds_blk],ax 0 00007EE0 8916[0E00] mov [fdos_hds_blk+2],dx 0 00007EE4 F9 stc ; return error 349 <1> select_dir20: 0 00007EE5 5B pop bx 0 00007EE6 1F pop ds 0 00007EE7 C3 ret 353 <1> 354 <1> 355 <1> ; Run down the path and parse final name 356 <1> ; exit: ds:dx -> info_fcb parsed at path end 357 <1> ; cf = 1, and al = code on any error 358 <1> 359 <1> path_prep: 0 00007EE8 C43E[6000] les di,[fdos_pb+2] ; es:di -> path name 361 <1> 362 <1> path_prep_ptr: 0 00007EEC E80900 call path_prep_check ; try to prepare path 0 00007EEF 7306 jnc path_prep_good ; skip if success 0 00007EF1 E932EF jmp fdos_error ; return error to application 366 <1> 367 <1> path_prep_drive_error: 368 <1> ; stc ; return CY set 0 00007EF4 B8F1FF mov ax,ED_DRIVE ; with correct error code 370 <1> path_prep_good: 0 00007EF7 C3 ret 372 <1> 373 <1> path_prep_check: 0 00007EF8 E84401 call get_path_drive ; from asciiz or default 0 00007EFB 72F7 jc path_prep_drive_error ; continue if drive A: - Z: 376 <1> path_prep_cont: 0 00007EFD 57 push di ; DX = drive code (0-15) 0 00007EFE 06 push es ; save string address 0 00007EFF 1E push ds 0 00007F00 07 pop es ; ES = SYSDAT 0 00007F01 E899FE call select_unique ; select the drive and 0 00007F04 07 pop es 0 00007F05 5E pop si ; es:si -> past drive 384 <1> 0 00007F06 26AC es lodsb ; get first character 0 00007F08 E8FE05 call check_slash ; if '\' or '/' then start at root 0 00007F0B 7518 jne path_prep_curdir ; else select current directory 0 00007F0D 06 push es 0 00007F0E E80001 call path_prep_root ; fake a '.' entry for the root 0 00007F11 07 pop es 391 <1> path_prep_cont05: 0 00007F12 26AC es lodsb ; get next char 0 00007F14 4E dec si ; forget we looked 0 00007F15 84C0 test al,al ; if just a '\' stop now 395 <1> ; jz path_prep_done 0 00007F17 7503 jnz path_prep_cont10 0 00007F19 E98C00 jmp path_prep_done 398 <1> path_prep_cont10: 0 00007F1C E8EA05 call check_slash 0 00007F1F 753A jne path_prep_next ; otherwise start processing from root 0 00007F21 26AC es lodsb 0 00007F23 EBED jmp path_prep_cont05 403 <1> ; mov ax,ED_ACCESS ; get correct error code 404 <1> ; stc ; and return if \\. 405 <1> ; ret 406 <1> 407 <1> path_prep_curdir: 408 <1> ; We need to select the current directory as a start for our operations 0 00007F25 4E dec si ; forget about char we looked at 0 00007F26 06 push es 0 00007F27 56 push si ; and save position in name 0 00007F28 A0[0000] mov al,[logical_drv] ; get the current logical drive 0 00007F2B E8[0000] call get_ldt ; and hence the LDT structures 0 00007F2E 7229 jc path_prep_curdir30 ; no LDT, leave at physical root 415 <1> %ifdef JOIN 0 00007F30 A0[1400] mov al,[fdos_hds_drv] ; are we on a known drive ? 0 00007F33 262A474D sub al,[es:LDT_DRV + bx] ; (we may be on joined drive) 0 00007F37 750E jne path_prep_curdir10 ; if not better rebuild 0 00007F39 98 cbw 0 00007F3A 48 dec ax ; AX = FFFF 421 <1> %else 422 <1> mov ax,0FFFFh 423 <1> %endif 0 00007F3B 263B4749 cmp ax,[es:LDT_BLK + bx] ; do we need to do a rebuild 0 00007F3F 7509 jne path_prep_curdir20 ; or can we trust the media ? 0 00007F41 263B4751 cmp ax,[es:LDT_BLKH + bx] 0 00007F45 7503 jne path_prep_curdir20 428 <1> path_prep_curdir10: 0 00007F47 E80DFF call rebuild_ldt_curdir ; better reselect current dir 430 <1> path_prep_curdir20: 0 00007F4A 268B4749 mov ax,[es:LDT_BLK + bx] ; move to current directory block 0 00007F4E 268B5751 mov dx,[es:LDT_BLKH + bx] 0 00007F52 A3[0C00] mov [fdos_hds_blk],ax 0 00007F55 8916[0E00] mov [fdos_hds_blk+2],dx 435 <1> path_prep_curdir30: 0 00007F59 5E pop si 0 00007F5A 07 pop es ; ES:SI -> name again 438 <1> 439 <1> path_prep_next: 440 <1> ;-------------- 441 <1> ; Called by disk change code to rebuild an HDS_ for a drive after 442 <1> ; media change detected. 443 <1> ; On Entry: 444 <1> ; ES:SI -> pathname to rebuild 445 <1> ; fdos_hds = HDS_ to rebuild 446 <1> ; On Exit: 447 <1> ; CY set if problem (AX=error code) 448 <1> ; ES=DS 449 <1> ; 0 00007F5B 26803C00 cmp byte ptr [es:si],0 ; can't have trailing '/' or '\' 0 00007F5F 7442 je path_prep_error ; return this as an error 452 <1> 0 00007F61 A1[0A00] mov ax,[path_drive] 0 00007F64 40 inc ax ; al = drive (one based) 0 00007F65 E88904 call parse_path ; set up the info_fcb 0 00007F68 7239 jc path_prep_error ; skip on any parse error 457 <1> 0 00007F6A 84C0 test al,al ; AL = delimiter 0 00007F6C 743A jz path_prep_done ; are we at the end ? 460 <1> 0 00007F6E 813E[2900]2E20 cmp word [info_fcb+1],'. ' ; NASM port swapped text literals 0 00007F74 74E5 je path_prep_next ; CHDIR (".") => stay where we are 463 <1> 0 00007F76 E83D04 call check_no_wild ; no wilds cards in path's 0 00007F79 7428 je path_prep_error ; skip if wild cards found 466 <1> 467 <1> %ifdef JOIN 0 00007F7B 06 push es 0 00007F7C 56 push si 0 00007F7D E8EA09 call offer_join ; are we opening a JOIN'd drive ? 0 00007F80 5E pop si 0 00007F81 07 pop es 0 00007F82 73D7 jnc path_prep_next ; if so move on to next stage 474 <1> %endif 0 00007F84 06 push es 0 00007F85 56 push si ; save string address 0 00007F86 1E push ds 0 00007F87 07 pop es ; ES = local segment 0 00007F88 E8[0000] call finddfcbf ; locate the directory entry 0 00007F8B 5E pop si 0 00007F8C 07 pop es ; restore string address 0 00007F8D 7414 jz path_prep_error ; no, missing directory in path 483 <1> 0 00007F8F F6470B10 test byte [DATTS + bx],DA_DIR ; check if directory 0 00007F93 740E jz path_prep_error ; fail if this is a file 486 <1> 0 00007F95 06 push es 0 00007F96 56 push si ; save string address 0 00007F97 1E push ds 0 00007F98 07 pop es ; ES = local segment 491 <1> %ifdef PASSWORD 0 00007F99 E8430B call check_pwd_any ; check if PW req'd & supplied 493 <1> %endif 0 00007F9C E8D902 call open_dir ; go down one level 0 00007F9F 5E pop si 0 00007FA0 07 pop es ; restore string address 0 00007FA1 73B8 jnc path_prep_next ; if open is good, repeat 498 <1> path_prep_error: 0 00007FA3 B8FDFF mov ax,ED_PATH ; return code in case of error 0 00007FA6 F9 stc ; indicate error to caller 0 00007FA7 C3 ret 502 <1> 503 <1> 504 <1> path_prep_done: 0 00007FA8 803E[2900]2E cmp byte [info_fcb+1],'.' ; is it '.' or '..' ? 0 00007FAD 755E jne path_prep_exit ; if so get its full name 507 <1> %ifdef JOIN 0 00007FAF E8B809 call offer_join ; are we opening a JOIN'd drive ? 0 00007FB2 735D jnc path_prep_root ; if so move into the dir 510 <1> %endif 0 00007FB4 E8[0000] call finddfcbf ; find the directory entry 0 00007FB7 7454 jz path_prep_exit ; stop if we can't 0 00007FB9 E8BC02 call open_dir ; move into the directory 0 00007FBC 72E5 jc path_prep_error ; stop if we can't 515 <1> ; mov cx,DBLOCK1[bx] ; are we destined for the root ? 0 00007FBE 837F1A00 cmp word ptr [DBLOCK1 + bx],0 ; are we destined for the root ? 0 00007FC2 750D jne path_prep_done10 ; no, proceed 0 00007FC4 833E[0000]00 cmp word [dosfat],FAT32 ; FAT32 file system? 519 <1> ; jcxz path_prep_root ; yes, stop - we won't find anything 0 00007FC9 7546 jne path_prep_root ; no, stop - we won't find anything 0 00007FCB 837F1400 cmp word [DBLOCK1H + bx],0 ; else also check high word of cluster 0 00007FCF 7440 je path_prep_root 523 <1> path_prep_done10: 0 00007FD1 FF36[1200] push word [fdos_hds_root+2] 0 00007FD5 FF36[1000] push word [fdos_hds_root] 0 00007FD9 C706[1000]0000 mov word [fdos_hds_root],0 ; don't stop at virtual root 0 00007FDF C706[1200]0000 mov word [fdos_hds_root+2],0 0 00007FE5 E86303 call find_parent ; find the parental entry 0 00007FE8 8F06[1000] pop word [fdos_hds_root] 0 00007FEC 8F06[1200] pop word [fdos_hds_root+2] 0 00007FF0 74B1 jz path_prep_error ; (shouldn't happen) 0 00007FF2 31C0 xor ax,ax 0 00007FF4 833E[0000]00 cmp word [dosfat],FAT32 ; FAT32 filesystem? 0 00007FF9 7403 je path_prep_done15 ; then assume no password set 0 00007FFB 8B470E mov ax,[DPWD + bx] ; get password hash code from entry 536 <1> path_prep_done15: 0 00007FFE A3[7000] mov [local_password],ax ; ensure we can get back down 0 00008001 8D37 lea si,[DNAME + bx] ; point to it's name 0 00008003 B90B00 mov cx,11 0 00008006 1E push ds 0 00008007 07 pop es 0 00008008 BF[2900] mov di,offset info_fcb+1 0 0000800B F3A4 rep movsb ; copy parental name to info_fcb 544 <1> path_prep_exit: 0 0000800D 1E push ds 0 0000800E 07 pop es ; restore ES to local segment 0 0000800F F8 clc 0 00008010 C3 ret 549 <1> 550 <1> 551 <1> path_prep_root: 0 00008011 1E push ds 0 00008012 07 pop es ; ES = local segment 0 00008013 A0[2800] mov al,[info_fcb] ; preserve drive setting 0 00008016 E80600 call clear_info_fcb 0 00008019 C606[2900]2E mov byte [info_fcb+1],'.' ; fake a '.' directory 0 0000801E C3 ret 558 <1> 559 <1> 560 <1> clear_info_fcb: 561 <1> ;-------------- 562 <1> ; Sets up a clean info_fcb for later use 563 <1> ; On Entry: 564 <1> ; AL = drive 565 <1> ; On Exit: 566 <1> ; All regs preserved 567 <1> ; 0 0000801F 57 push di 0 00008020 51 push cx 0 00008021 50 push ax 0 00008022 BF[2800] mov di,offset info_fcb 0 00008025 AA stosb ; set the drive code 573 <1> 0 00008026 B90B00 mov cx,11 0 00008029 B020 mov al,' ' 0 0000802B F3AA rep stosb ; fill name with blanks 577 <1> %ifdef PASSWORD 0 0000802D B90800 mov cx,8 0 00008030 BF[7200] mov di,offset password_buffer 0 00008033 F3AA rep stosb ; blank password buffer 0 00008035 26890E[7000] mov [es:local_password],cx ; zero out local password 582 <1> %endif 0 0000803A 58 pop ax 0 0000803B 59 pop cx 0 0000803C 5F pop di 0 0000803D F8 clc 0 0000803E C3 ret 588 <1> 589 <1> 590 <1> ; Get drive from path name, or if none, use default drive 591 <1> ; On Entry: 592 <1> ; es:di -> path name 593 <1> ; On Exit: 594 <1> ; AL = path_drive = specified or default drive 595 <1> ; es:di -> past drive name 596 <1> ; cf = 1 if illegal drive name 597 <1> 598 <1> get_path_drive: 0 0000803F 26803D00 cmp byte ptr [es:di],0 ; check if string is empty 0 00008043 7425 je get_path_error ; which isn't O.K. at all 0 00008045 26807D013A cmp byte ptr [es:1 + di],':' ; if the second char is ':', 0 0000804A 7405 jz get_path_explicit ; then drive is in pathname 0 0000804C E8AC08 call current_dsk2al 0 0000804F EB13 jmp get_path_ok ; common code from here 605 <1> 606 <1> get_path_explicit: 0 00008051 268A05 mov al,[es:di] ; grab the drive designator 0 00008054 E8BA04 call toupper ; make sure it is upper case 0 00008057 2C41 sub al,'A' ; correct offset. if too 0 00008059 720F jb get_path_error ; small, return error 0 0000805B 363A06[0000] cmp al,[ss:last_drv] 0 00008060 7308 jae get_path_error 0 00008062 47 inc di 0 00008063 47 inc di ; it's ok, bump the pointer 615 <1> get_path_ok: 0 00008064 30E4 xor ah,ah ; zero ah and clc 0 00008066 A3[0A00] mov [path_drive],ax ; save for other functions 0 00008069 C3 ret 619 <1> 620 <1> get_path_error: 0 0000806A F9 stc ; flag the error 0 0000806B C3 ret 623 <1> 624 <1> asciiz_dev_offer: 625 <1> ;---------------- 626 <1> ; On Entry: 627 <1> ; PB+2 -> pathname 628 <1> ; On Exit: 629 <1> ; Only come back if not a device 630 <1> ; 631 <1> ; See if the filename is that of a simple device 632 <1> ; eg. 'CON', 'A:CON', 'CON.EXT' 633 <1> ; We should also accept '\DEV' format 634 <1> ; eg. '\DEV\CON', "A:\DEV\CON' 635 <1> ; More complicated forms should be ignored - they will be handled 636 <1> ; after the pathname is parsed. 637 <1> ; eg. 'A:\CON', '\CON', 'SUBDIR\CON.EXT' 638 <1> ; 0 0000806C 1E push ds 0 0000806D 8B7602 mov si,[2 + bp] ; SI -> parameter block 0 00008070 C57402 lds si,[2 + si] ; DS:SI -> file specification 0 00008073 803C00 cmp byte ptr [0 + si],0 ; NUL names are stupid, but 0 00008076 7465 je asciiz_dev_offer30 ; you do get them.... 0 00008078 807C013A cmp byte ptr [1 + si],':' ; is a drive specified 0 0000807C 7502 jne asciiz_dev_offer10 0 0000807E 46 inc si 0 0000807F 46 inc si ; skip that, but no more 648 <1> asciiz_dev_offer10: 0 00008080 16 push ss 0 00008081 07 pop es ; ES:DI -> scratch FCB in build 0 00008082 BF[0000] mov di,offset name_buf ; name in pcmode data buffer 0 00008085 B020 mov al,' ' 0 00008087 B90B00 mov cx,8+3 0 0000808A F3AA rep stosb ; start by clearing name 655 <1> 0 0000808C 8A04 mov al,[si] ; beware of '\DEV\name' format.. 0 0000808E E87804 call check_slash ; if not slash carry on 0 00008091 7521 jne asciiz_dev_offer15 0 00008093 AC lodsb ; possible, lets look at rest 0 00008094 AC lodsb 0 00008095 E87904 call toupper 0 00008098 3C44 cmp al,'D' ; is '\D'possible ? 0 0000809A 7541 jne asciiz_dev_offer30 0 0000809C AC lodsb 0 0000809D E87104 call toupper 0 000080A0 3C45 cmp al,'E' ; is '\DE' on ? 0 000080A2 7539 jne asciiz_dev_offer30 0 000080A4 AC lodsb 0 000080A5 E86904 call toupper 0 000080A8 3C56 cmp al,'V' ; is '\DEV' on ? 0 000080AA 7531 jne asciiz_dev_offer30 0 000080AC AC lodsb ; finally how about trailing '\' 0 000080AD E85904 call check_slash 0 000080B0 752B jne asciiz_dev_offer30 0 000080B2 8A04 mov al,[si] ; check for delimiter 676 <1> asciiz_dev_offer15: 0 000080B4 E81504 call check_delim ; if first char = delimiter 0 000080B7 7424 jz asciiz_dev_offer30 ; then it can't be a device 679 <1> 0 000080B9 BF[0000] mov di,offset name_buf ; build name in scratch FCB 0 000080BC B90800 mov cx,8 ; length of name field 0 000080BF E8D903 call parse_one ; parse just the name 0 000080C2 3C2E cmp al,'.' 0 000080C4 7509 jnz asciiz_dev_offer20 ; do we have to parse an extention ? 0 000080C6 BF[0800] mov di,offset name_buf+8 ; di -> fcb ext field 0 000080C9 B90300 mov cx,3 ; length of ext field 0 000080CC E8CC03 call parse_one ; parse just extension 688 <1> asciiz_dev_offer20: 0 000080CF 84C0 test al,al ; if not a NUL by now forget it 0 000080D1 750A jnz asciiz_dev_offer30 0 000080D3 16 push ss 0 000080D4 1F pop ds 0 000080D5 BE[0000] mov si,offset name_buf ; DS:SI -> name 0 000080D8 E83F00 call check_device_common ; try to find the name 0 000080DB 7304 jnc asciiz_dev_accept ; if we can handle it here 696 <1> asciiz_dev_offer30: 0 000080DD 1F pop ds ; DS back to normal 0 000080DE 16 push ss 0 000080DF 07 pop es ; ditto with ES 0 000080E0 C3 ret ; not a device - proceed 701 <1> 702 <1> asciiz_dev_accept: 703 <1> ;---------------- 704 <1> ; We have found a match in the device at ES:BX 705 <1> ; 0 000080E1 36891E[0000] mov word ptr [ss:current_device],bx 0 000080E6 368C06[0200] mov word ptr [ss:current_device+2],es 0 000080EB 1F pop ds ; DS = SYSDAT again 0 000080EC 58 pop ax ; discard return address 0 000080ED E8DFEC call local_disk ; we need the MX 0 000080F0 36C41E[0000] les bx,[ss:current_device] ; ES:BX -> device header 0 000080F5 833E[5E00]55 cmp word [fdos_pb],FD_EXPAND 0 000080FA 740D je asciiz_dev_accept20 0 000080FC 833E[5E00]4E cmp word [fdos_pb],4Eh ; is it FD_FFIRST ? 0 00008101 7403 je asciiz_dev_accept10 0 00008103 E9[0000] jmp open_dev ; open the device locally 717 <1> asciiz_dev_accept10: 0 00008106 E9[0000] jmp first_dev ; 'find' the device locally 719 <1> asciiz_dev_accept20: 0 00008109 E961FA jmp expand_dev ; 'expand' the device locally 721 <1> 722 <1> chk_no_dev: ; check file is not a character device 723 <1> ;---------- 724 <1> ; On Entry: 725 <1> ; info_fcb contains parsed filename 726 <1> ; On Exit: 727 <1> ; Don't return if it's a character device 728 <1> ; 0 0000810C E80800 call check_device ; is this a device ? 0 0000810F 7303 jnc chk_not_dev10 0 00008111 1E push ds 0 00008112 07 pop es ; ES points to data again 0 00008113 C3 ret 734 <1> chk_not_dev10: 0 00008114 E948ED jmp fdos_ED_ACCESS ; blow caller away 736 <1> 737 <1> check_device: 738 <1> ;------------ 739 <1> ; On Entry: 740 <1> ; info_fcb contains parsed filename 741 <1> ; On Exit: 742 <1> ; CY set if not found 743 <1> ; else 744 <1> ; CY clear if found 745 <1> ; ES:BX -> device header 746 <1> ; 0 00008117 BE[2900] mov si,offset info_fcb+1 ; DS:SI -> name to check 748 <1> ; jmp check_device_common 749 <1> 750 <1> check_device_common: 751 <1> ;------------------- 752 <1> ; On Entry: 753 <1> ; DS:SI -> 8 byte buffer to check 754 <1> ; On Exit: 755 <1> ; CY set if not found 756 <1> ; else 757 <1> ; CY clear if found 758 <1> ; ES:BX -> device header 759 <1> ; 0 0000811A 16 push ss 0 0000811B 07 pop es ; Get the PCMODE Data Segment 0 0000811C BB[0000] mov bx,offset dev_root ; hence the Device List 0 0000811F 89F0 mov ax,si ; keep copy of start in AX 764 <1> check_device10: 765 <1> DEVHDR.ATTRIB equ ATTRIB ; NASM port label 0 00008121 26F747040080 test word [es:DEVHDR.ATTRIB + bx],DA_CHARDEV 0 00008127 740A jz check_device20 ; skip unless it's a character device 768 <1> DEVHDR.NAM equ NAM ; NASM port label 0 00008129 8D7F0A lea di,[DEVHDR.NAM + bx] ; ES:DI -> device name 0 0000812C B90400 mov cx,8/2 ; compare file name w/o extension 0 0000812F F3A7 repe cmpsw ; compare until CX == 0 or mismatch 0 00008131 740B je check_device30 773 <1> check_device20: 0 00008133 89C6 mov si,ax ; restore starting address 775 <1> DEVHDR.NEXT equ NEXT ; NASM port label 0 00008135 26C41F les bx,[es:DEVHDR.NEXT + bx] ; get next device driver 0 00008138 83FBFF cmp bx,0FFFFh ; end of the chain ? 0 0000813B 75E4 jne check_device10 0 0000813D F9 stc ; indicate character device not found 780 <1> check_device30: 0 0000813E C3 ret 782 <1> 783 <1> 784 <1> no_dir_vol: 785 <1> ;---------- 0 0000813F F6470B18 test byte [DATTS + bx],DA_DIR+DA_VOLUME 0 00008143 7501 jnz dir_vol_err ; return error if label or directory 0 00008145 C3 ret ; else it's O.K. 789 <1> dir_vol_err: 0 00008146 E916ED jmp fdos_ED_ACCESS ; return "access denied" 791 <1> 792 <1> 793 <1> 794 <1> get_pb2_drive: 795 <1> ;------------- 0 00008149 A0[6000] mov al,byte ptr [fdos_pb+2] ; get requested drive code 0 0000814C FEC8 dec al ; Get the default drive if 0 0000814E 7903 jns get_pb2_drv1 ; the requested drive is 00 0 00008150 E8A807 call current_dsk2al ; AL = default drive 800 <1> get_pb2_drv1: 0 00008153 C3 ret 802 <1> 803 <1> 804 <1> mkdir_init: 805 <1> ;---------- 0 00008154 52 push dx 0 00008155 50 push ax ; Init 1st block of the directory 0 00008156 E8[0000] call zeroblk ; zero the block 809 <1> ; pop ax ! push ax ; get the block number 0 00008159 58 pop ax 0 0000815A 5A pop dx ; get the block number 0 0000815B 52 push dx 0 0000815C 50 push ax 0 0000815D 31DB xor bx,bx ; seek to beginning of cluster 0 0000815F E8[0000] call fill_dirbuf ; DI -> directory entry 816 <1> ; pop dx ! push dx ; get our own block # 0 00008162 58 pop ax 0 00008163 5A pop dx ; get our own block # 0 00008164 52 push dx 0 00008165 50 push ax 821 <1> ; mov ax,' .' ; this is the "." directory 0 00008166 B92E20 mov cx,'. ' ; this is the "." directory ; NASM port swapped text literals 0 00008169 E81100 call init_dot ; set name, attrib, time, date, block1 0 0000816C E8[0000] call flush_dirbuf ; copy '.' entry to sector buffer 0 0000816F 58 pop ax ; get the block number 0 00008170 5A pop dx 0 00008171 BB0100 mov bx,1 ; do 2nd entry 0 00008174 E8[0000] call fill_dirbuf ; DI -> directory entry 0 00008177 E85401 call hdsblk 830 <1> ; xchg ax,dx ; DX = parent directory 831 <1> ; mov ax,'..' ; this is the ".." directory 0 0000817A B92E2E mov cx,'..' ; this is the ".." directory 833 <1> ; call init_dot ; fall into INIT_DOT 834 <1> ; ret 835 <1> 836 <1> init_dot: 0 0000817D 893E[0000] mov [dirp],di ; save directory entry for SETPCD 0 00008181 57 push di 839 <1> ; mov DBLOCK1[di],dx ; our own block # 0 00008182 89451A mov [DBLOCK1 + di],ax ; our own block # 0 00008185 833E[0000]00 cmp word [dosfat],FAT32 ; 32-bit file system? 0 0000818A 7503 jne init_dot10 ; no, do not use high cluster entry 0 0000818C 895514 mov [DBLOCK1H + di],dx 844 <1> init_dot10: 0 0000818F 91 xchg ax,cx 0 00008190 AB stosw ; store "." or ".." 0 00008191 B020 mov al,' ' 0 00008193 B90900 mov cx,11-2 0 00008196 F3AA rep stosb ; pad the name with spaces 0 00008198 B010 mov al,DA_DIR 0 0000819A AA stosb ; attribute = directory 0 0000819B E8DD08 call GetTOD ; get time/date of creation 0 0000819E 5B pop bx 0 0000819F E9C308 jmp stamp_date_and_time ; set date DX and time AX in dir BX 855 <1> 856 <1> 857 <1> ; Utility functions for RMDIR and UNLINK 858 <1> 859 <1> rmdir_ok: ; make sure directory not in use 860 <1> ;-------- 861 <1> ; 862 <1> 0 000081A2 8B1E[0000] mov bx,[dirp] ; get the directory entry 0 000081A6 8B471A mov ax,[DBLOCK1 + bx] ; block number of directory 0 000081A9 31D2 xor dx,dx 0 000081AB 833E[0000]00 cmp word [dosfat],FAT32 ; FAT32 file system? 0 000081B0 7503 jne rmdir_ok05 ; no, then skip high word of cluster 0 000081B2 8B5714 mov dx,[DBLOCK1H + bx] 869 <1> rmdir_ok05: 0 000081B5 31DB xor bx,bx ; start at beginning 871 <1> rmdir_ok1: 0 000081B7 52 push dx 0 000081B8 50 push ax 0 000081B9 53 push bx ; save block, offset 0 000081BA E8[0000] call fill_dirbuf ; locate directory entry 0 000081BD 5B pop bx 0 000081BE 58 pop ax ; restore offset, block 0 000081BF 5A pop dx 0 000081C0 803D00 cmp byte [DNAME + di],0 ; is it virgin entry? 0 000081C3 7446 je rmdir_ok4 ; yes, no entries above here 0 000081C5 803DE5 cmp byte [DNAME + di],0E5h ; is it deleted entry? 0 000081C8 7427 je rmdir_ok3 ; yes, no problems yet... 0 000081CA 803D2E cmp byte [DNAME + di],'.' ; is it "." or ".."? 0 000081CD 7422 je rmdir_ok3 0 000081CF 89FB mov bx,di 0 000081D1 E8[0000] call is_lfn ; check if it is a long filename 0 000081D4 721B jc rmdir_ok3 ; we do not care for orphaned LFNs 888 <1> %ifdef DELWATCH 889 <1> ; We have found a dir entry - better check if it is a pending delete 890 <1> ; and that delwatch is installed. Then we can ignore it. 0 000081D6 F6450B08 test byte [DATTS + di],DA_VOLUME ; is the volume label bit set 0 000081DA 740F jz rmdir_not_empty ; no, can't be pending delete 0 000081DC 52 push dx 0 000081DD 31D2 xor dx,dx ; (also sets DH = DELW_RDMASK) 895 <1> ; cmp dx,DBLOCK1[di] ; is it really a pending delete ? 896 <1> ; jz rmdir_not_empty ; yes, fall thru to delwatch check 0 000081DF 92 xchg ax,dx ; AH = DELW_RDMASK, DX = dir cluster 0 000081E0 89FE mov si,di ; -> directory buffer (for DELWATCH) 0 000081E2 36FF1E[0000] call far [ss:fdos_stub] ; is the delwatch TSR installed 0 000081E7 92 xchg ax,dx ; AX = dir cluster 0 000081E8 5A pop dx 0 000081E9 7306 jnc rmdir_ok3 ; delwatch will handle pending deletes 903 <1> rmdir_not_empty: 904 <1> %endif 0 000081EB B8FBFF mov ax,ED_ACCESS ; return "access denied" if not empty 906 <1> 907 <1> rmdir_inuse: ; directory not empty or in use: 0 000081EE E935EC jmp fdos_error ; return the error 909 <1> 910 <1> rmdir_ok3: ; else this entry O.K. 0 000081F1 43 inc bx ; check next directory entry 0 000081F2 3B1E[0000] cmp bx,[dirperclu] ; cluster completed? 0 000081F6 72BF jb rmdir_ok1 ; loop back if more to come 0 000081F8 E8[0000] call getnblk ; get next block in directory 0 000081FB 29DB sub bx,bx ; start at beginning of block 916 <1> ; cmp ax,lastcl ; end of cluster chain? 0 000081FD 3B16[0200] cmp dx,[blastcl+2] ; end of cluster chain? 0 00008201 72B4 jb rmdir_ok1 ; loop back if not done yet 0 00008203 7706 ja rmdir_ok4 0 00008205 3B06[0000] cmp ax,[blastcl] 0 00008209 72AC jb rmdir_ok1 922 <1> rmdir_ok4: ; directory is empty 0 0000820B A0[0000] mov al,[adrive] 0 0000820E E8[0000] call hshdscrd ; discard the hash values 0 00008211 F8 clc ; "go ahead with RMDIR..." 0 00008212 C3 ret ; return, ready for the evil deed... 927 <1> 928 <1> 929 <1> chkcds: ; check if any process uses directory to delete 930 <1> ;------ 931 <1> ; On Entry: 932 <1> ; dirp -> directory entry of DIR to check 933 <1> ; On Exit: 934 <1> ; CY clear if DIR is in use 935 <1> ; 0 00008213 8B1E[0000] mov bx,[dirp] 0 00008217 8B4F1A mov cx,[DBLOCK1 + bx] ; block number of directory to delete 0 0000821A 890E[0400] mov [chkcds_cl],cx 0 0000821E 31C9 xor cx,cx 0 00008220 833E[0000]00 cmp word [dosfat],FAT32 ; id this a FAT32 file system? 0 00008225 7503 jne chkcds05 ; no, proceed 0 00008227 8B4F14 mov cx,[DBLOCK1H + bx] ; else load high word of cluster, too 943 <1> chkcds05: 0 0000822A 890E[0600] mov [chkcds_cl+2],cx 0 0000822E 8A16[0000] mov dl,[physical_drv] ; get the drive the subdir is in 0 00008232 B0FF mov al,-1 ; start with drive A: 947 <1> chkcds10: 0 00008234 40 inc ax ; next drive 0 00008235 E8[0000] call get_ldt_raw ; ES:BX -> LDT for drive 0 00008238 723D jc chkcds20 ; bail if if bad drive 0 0000823A 26F64744C0 test byte ptr [es:LDT_FLAGS+1 + bx],(LFLG_NETWRKD+LFLG_PHYSICAL)/100h 0 0000823F 78F3 js chkcds10 ; it can't be a network drive 0 00008241 74F1 jz chkcds10 ; it must be a physical drive 0 00008243 263A574D cmp dl,[es:LDT_DRV + bx] ; does the drive match? 0 00008247 75EB jne chkcds10 ; no, don't bother then 0 00008249 26837F49FF cmp word [es:LDT_BLK + bx],0ffffh ; is it valid 0 0000824E 7513 jne chkcds19 0 00008250 26837F51FF cmp word [es:LDT_BLKH + bx],0ffffh 0 00008255 750C jne chkcds19 0 00008257 50 push ax 0 00008258 51 push cx 0 00008259 52 push dx 0 0000825A E8[0000] call select_logical_drv ; select with media change check 0 0000825D E8F7FB call rebuild_ldt_curdir ; rebuild LDT_ 0 00008260 5A pop dx 0 00008261 59 pop cx 0 00008262 58 pop ax 968 <1> chkcds19: 969 <1> %if 0 970 <1> ; This didn't make the beta, so leave until the next release 971 <1> ; We really need to make sure we relog all SUBST's drives before 972 <1> ; we can be sure this is valid and fail the rmdir 973 <1> mov cx,[chkcds_cl] 974 <1> cmp cx,[es:LDT_ROOT + bx] ; is this our root block ? 975 <1> jne chkcds19a 976 <1> mov cx,[chkcds_cl+2] 977 <1> cmp cx,[es:LDT_ROOTH + bx] 978 <1> je chkcds20 ; (ie. a SUBST'd drive) 979 <1> chkcds19a: 980 <1> %endif 0 00008263 8B0E[0400] mov cx,[chkcds_cl] 0 00008267 263B4F49 cmp cx,[es:LDT_BLK + bx] ; does the block match 0 0000826B 75C7 jne chkcds10 ; no, try next drive 0 0000826D 8B0E[0600] mov cx,[chkcds_cl+2] 0 00008271 263B4F51 cmp cx,[es:LDT_BLKH + bx] 0 00008275 75BD jne chkcds10 987 <1> chkcds20: 0 00008277 C3 ret 989 <1> 990 <1> 991 <1> ; 992 <1> ; Go down one level in directory 993 <1> ; On Entry: 994 <1> ; DIRP -> directory to open 995 <1> ; PATH_DRIVE = drive to use 996 <1> ; On Exit: 997 <1> ; DX:AX = fdos_hds_blk (the current directory block) 998 <1> ; CY clear on success 999 <1> ; CY set on error 1000 <1> ; 1001 <1> 1002 <1> open_dir: 0 00008278 8B1E[0000] mov bx,[dirp] 0 0000827C F6470B10 test byte [DATTS + bx],DA_DIR ; check if directory 0 00008280 F9 stc 0 00008281 744A jz open_dir20 ; fail if this is a file 0 00008283 813E[2900]2E2E cmp word [info_fcb+1],'..' 0 00008289 7525 jne open_dir10 ; watch out if going up a level 0 0000828B A1[0C00] mov ax,[fdos_hds_blk] ; get current block 0 0000828E 8B16[0E00] mov dx,[fdos_hds_blk+2] 0 00008292 3B06[1000] cmp ax,[fdos_hds_root] ; check if at logical root already 0 00008296 7518 jne open_dir10 ; and if not carry on 0 00008298 3B16[1200] cmp dx,[fdos_hds_root+2] 0 0000829C 7512 jne open_dir10 0 0000829E 3B471A cmp ax,[DBLOCK1 + bx] ; if we are already at the virtual root 0 000082A1 F9 stc ; and want to stay there that's OK 0 000082A2 7529 jne open_dir20 ; otherwise return an error 0 000082A4 833E[0000]00 cmp word [dosfat],FAT32 ; 32-bit cluster values in dir entry? 0 000082A9 7505 jne open_dir10 ; no, continue 0 000082AB 3B5714 cmp dx,[DBLOCK1H + bx] ; else check high word of cluster, too 0 000082AE 751D jne open_dir20 1022 <1> open_dir10: 0 000082B0 A0[0000] mov al,[physical_drv] ; remember the drive 0 000082B3 A2[1400] mov [fdos_hds_drv],al 0 000082B6 8B471A mov ax,[DBLOCK1 + bx] ; remember this directory block 0 000082B9 31D2 xor dx,dx 0 000082BB 833E[0000]00 cmp word [dosfat],FAT32 ; 32-bit file system? 0 000082C0 7503 jnz open_dir15 ; no, then leave high word at zero 0 000082C2 8B5714 mov dx,[DBLOCK1H + bx] ; else read it from dir entry 1030 <1> open_dir15: 0 000082C5 A3[0C00] mov [fdos_hds_blk],ax 0 000082C8 8916[0E00] mov [fdos_hds_blk+2],dx 0 000082CC F8 clc ; success 1034 <1> open_dir20: 0 000082CD C3 ret 1036 <1> 1037 <1> 1038 <1> Public hdsblk 1039 <1> 1040 <1> ;====== 1041 <1> hdsblk: ;/* check if we are in subdirectory */ 1042 <1> ;====== 1043 <1> ; 1044 <1> ; exit: DX:AX = directory block number 1045 <1> ; ZF = set if at root 1046 <1> ; regs: others preserved 1047 <1> 0 000082CE A1[0C00] mov ax,[fdos_hds_blk] ; get current directory block 0 000082D1 8B16[0E00] mov dx,[fdos_hds_blk+2] 0 000082D5 85C0 test ax,ax ; set ZF 0 000082D7 7502 jnz hdsblk10 0 000082D9 85D2 test dx,dx 1053 <1> hdsblk10: 0 000082DB C3 ret 1055 <1> 1056 <1> 1057 <1> 1058 <1> parent2save_area: 1059 <1> ;----------------- 1060 <1> ; On Entry: 1061 <1> ; DX:AX = cluster number of parent to find 1062 <1> ; On Exit: 1063 <1> ; save_area contains parental name (DX = length of name) 1064 <1> ; 0 000082DC E86C00 call find_parent ; locate parent directory 0 000082DF 743E jz path_error ; stop in case we're in a mess 0 000082E1 8D37 lea si,[DNAME + bx] ; get parent directory name 0 000082E3 BF[3400] mov di,offset save_area ; ES:DI -> scratch area 1069 <1> ; jmp unparse ; make it ASCIIZ file name 1070 <1> 1071 <1> ; build ASCIIZ string from directory entry 1072 <1> ; entry: BX -> directory buffer 1073 <1> ; ES:DI -> output buffer 1074 <1> ; exit: ES:DI -> next byte in buffer 1075 <1> 1076 <1> unparse: 1077 <1> ;------- 0 000082E6 57 push di ; save base of name 0 000082E7 B90800 mov cx,8 ; remainder of up to 7 characters 0 000082EA 8D37 lea si,[DNAME + bx] ; SI -> directory name 0 000082EC E82200 call unparse_field ; copy name, strip trailing blanks 0 000082EF B02E mov al,'.' 0 000082F1 AA stosb ; add the dot for start of extension 0 000082F2 57 push di ; remember where extention starts 0 000082F3 B90300 mov cx,3 ; copy 3-char extension 0 000082F6 8D7708 lea si,[DNAME+8 + bx] ; SI -> directory extention 0 000082F9 E81500 call unparse_field ; copy extension, strip trailing blanks 0 000082FC 58 pop ax ; recover start of extension 0 000082FD 39F8 cmp ax,di ; did we generate extension? 0 000082FF 7501 jne unparse1 ; skip if we did 0 00008301 4F dec di ; else eat the '.' 1092 <1> unparse1: 0 00008302 31C0 xor ax,ax 0 00008304 AA stosb ; NUL-terminate the name 0 00008305 5B pop bx ; ES:BX -> base of name 0 00008306 26803F05 cmp byte ptr [es:bx],05h 0 0000830A 7504 jne unparse2 ; if not mapped E5 (deleted entry/Kanji) 0 0000830C 26C607E5 mov byte ptr [es:bx],0E5h ; else map back to E5 for Kanji support 1099 <1> unparse2: 0 00008310 C3 ret 1101 <1> 1102 <1> unparse_field: 1103 <1> ;------------- 1104 <1> ; entry: DS:SI -> disk buffer 1105 <1> ; ES:DI -> ASCIIZ name to build 1106 <1> ; CX = field length 1107 <1> ; On Exit: 1108 <1> ; ES:DI -> end of name 1109 <1> ; BX preserved 1110 <1> 0 00008311 56 push si ; save start of field 0 00008312 01CE add si,cx ; SI -> end of field 0 00008314 41 inc cx ; one extra for LOOPE dec 1114 <1> unprsf10: 0 00008315 4E dec si ; lets look at the previous char 0 00008316 803C20 cmp byte ptr [si],' ' ; trailing space ? 0 00008319 E1FA loope unprsf10 0 0000831B 5E pop si ; SI = start of field 0 0000831C F3A4 rep movsb 0 0000831E C3 ret 1121 <1> 1122 <1> 1123 <1> path_error: 0 0000831F E933EB jmp fdos_ED_PATH ; return "invalid path" error 1125 <1> 1126 <1> mkspace_parent: 1127 <1> ;-------------- 1128 <1> ; save_area contains the parental name, DX bytes long. We wish to insert it 1129 <1> ; into an ASCIIZ string so make DX bytes of space at ES:DI. 1130 <1> ; On Entry: 1131 <1> ; ES:DI -> ASCIIZ, DX = byte count 1132 <1> ; On Exit: 1133 <1> ; DS:SI -> parents name, CX = length of parent (DX on entry) 1134 <1> ; 0 00008322 B000 mov al,0 ; find end of name 0 00008324 B98000 mov cx,128 ; max. path length 0 00008327 F2AE repne scasb ; scan for end of path 0 00008329 F7D9 neg cx 0 0000832B 81C18000 add cx,128 ; CX = string length including NUL 0 0000832F 89C8 mov ax,cx 0 00008331 01D0 add ax,dx 0 00008333 83F840 cmp ax,64 0 00008336 77E7 ja path_error 0 00008338 4F dec di ; ES:DI -> '\0' 0 00008339 89FE mov si,di ; SI -> source of copy 0 0000833B 01D7 add di,dx ; point to beyond insertion 0 0000833D 1E push ds 0 0000833E 06 push es 0 0000833F 1F pop ds ; move string backwards to make space 0 00008340 FD std 0 00008341 F3A4 rep movsb 0 00008343 FC cld ; for directory name 0 00008344 1F pop ds 0 00008345 89D1 mov cx,dx ; CX = length of new directory name 0 00008347 BE[3400] mov si,offset save_area ; SI -> unparsed name 0 0000834A C3 ret 1157 <1> 1158 <1> ; find parent directory starting with cluster AX 1159 <1> ; entry: DX:AX = cluster of parent to find 1160 <1> ; exit: ZF = 1 if not found (shouldn't happen) 1161 <1> ; -or- 1162 <1> ; ZF = 0 if found, BX=DIRP -> dir entry 1163 <1> 1164 <1> find_parent: 0 0000834B A3[2300] mov [blk],ax ; save the block number 0 0000834E 8916[2500] mov [blk+2],dx 0 00008352 1E push ds 0 00008353 07 pop es 0 00008354 BF[2900] mov di,offset info_fcb+1 0 00008357 B82E2E mov ax,'..' 0 0000835A AB stosw ; file name is '..' 0 0000835B B020 mov al,' ' ; pad with spaces 0 0000835D B90900 mov cx,9 0 00008360 F3AA rep stosb 0 00008362 E8[0000] call finddfcbf ; find pointer to parent 0 00008365 743D jz fndpar2 ; shouldn't happen... 0 00008367 E80EFF call open_dir ; go up one level 0 0000836A 7235 jc fndpar3 ; screwed up by security... 0 0000836C E8[0000] call setenddir ; search from beginning 1180 <1> fndpar1: 0 0000836F 29C9 sub cx,cx 0 00008371 E8[0000] call getdir ; find next directory entry 0 00008374 742E jz fndpar2 ; end of directory 0 00008376 8A07 mov al,[DNAME + bx] ; check if deleted file 0 00008378 3CE5 cmp al,0E5h 0 0000837A 74F3 je fndpar1 ; skip empty slots 0 0000837C 3C00 cmp al,0 0 0000837E 7424 je fndpar2 ; end of directory 0 00008380 F6470B10 test byte [DATTS + bx],DA_DIR ; try to find directory 0 00008384 74E9 jz fndpar1 ; skip plain files 0 00008386 8B471A mov ax,[DBLOCK1 + bx] ; get starting cluster 0 00008389 31D2 xor dx,dx 0 0000838B 833E[0000]00 cmp word [dosfat],FAT32 ; 32-bit file system? 0 00008390 7503 jne fndpar15 ; no, then skip high word of starting cluster 0 00008392 8B5714 mov dx,[DBLOCK1H + bx] 1196 <1> fndpar15: 0 00008395 3B06[2300] cmp ax,[blk] 0 00008399 75D4 jne fndpar1 0 0000839B 3B16[2500] cmp dx,[blk+2] 0 0000839F 75CE jne fndpar1 1201 <1> fndpar3: 0 000083A1 83C8FF or ax,0FFFFh ; force non-zero condition 1203 <1> fndpar2: 0 000083A4 C3 ret ; ZF = 0 if found 1205 <1> 1206 <1> path_prep_chk: 1207 <1> ;------------- 1208 <1> ; Run down the path and parse final name 1209 <1> ; exit: ds:dx -> info_fcb parsed at path end 1210 <1> 0 000083A5 E840FB call path_prep ; prepare the path 0 000083A8 E861FD call chk_no_dev ; devices not allowed 1213 <1> chk_no_dot_or_wild: 1214 <1> ;------------------ 0 000083AB E81DEB call chk_no_dot ; no subdirs entries either 1216 <1> ; jmp chk_no_wild ; wild cards not allowed 1217 <1> 1218 <1> chk_no_wild: ; make sure path doesn't contain wild cards 1219 <1> ;----------- ; (or is all spaces) 0 000083AE E80500 call check_no_wild ; error if any wildcards 0 000083B1 751D jne check_no_wild_ret ; or if all spaces 0 000083B3 E93CF8 jmp fdos_ED_FILE ; return "invalid filename" 1223 <1> 1224 <1> check_no_wild: ; make sure path doesn't contain wild cards 1225 <1> ;------------- ; (or is all spaces) ZF set on problem 0 000083B6 06 push es 0 000083B7 1E push ds 0 000083B8 07 pop es ; ES -> SYSDAT 0 000083B9 BF[2900] mov di,offset info_fcb+1 0 000083BC B90B00 mov cx,11 0 000083BF B03F mov al,'?' ; scan for wild cards 0 000083C1 F2AE repne scasb 0 000083C3 740A je check_no_wild_exit ; skip if wild cards found 0 000083C5 BF[2900] mov di,offset info_fcb+1 0 000083C8 B90B00 mov cx,11 0 000083CB B020 mov al,' ' ; scan for all spaces 0 000083CD F3AE repe scasb ; ZF set if a problem 1238 <1> check_no_wild_exit: 0 000083CF 07 pop es 1240 <1> check_no_wild_ret: 0 000083D0 C3 ret 1242 <1> 1243 <1> 1244 <1> chk_for_root: 1245 <1> ;------------ 1246 <1> ; On Entry: 1247 <1> ; info_fcb -> name of failed search 1248 <1> ; fdos_hds -> dir we searched in 1249 <1> ; On Exit: 1250 <1> ; ZF set if a search for root (or '.' in root) 1251 <1> ; 0 000083D1 833E[0C00]00 cmp word [fdos_hds_blk],0 ; are we in the root ? 0 000083D6 7518 jne chk_for_root10 ; no, no further checks required 0 000083D8 833E[0E00]00 cmp word [fdos_hds_blk+2],0 0 000083DD 7511 jne chk_for_root10 0 000083DF 1E push ds 0 000083E0 07 pop es 0 000083E1 BF[2900] mov di,offset info_fcb+1 0 000083E4 B02E mov al,'.' ; check for root 0 000083E6 AE scasb ; is it a '.' entry ? 0 000083E7 7507 jne chk_for_root10 0 000083E9 B90A00 mov cx,8+3-1 0 000083EC B020 mov al,' ' 0 000083EE F3AE repe scasb ; is it all spaces ? 1265 <1> chk_for_root10: 0 000083F0 C3 ret 1267 <1> 1268 <1> 1269 <1> ; Parse a pathname into an info_fcb 1270 <1> ; entry: es:si -> asciiz string 1271 <1> ; AX = drive code 1272 <1> ; exit: es:si -> next asciiz name in path 1273 <1> ; dx -> fcb 1274 <1> ; CY clear, AL = 0 if end of string 1275 <1> ; CY set, AX = error code 1276 <1> 1277 <1> parse_path: 1278 <1> ;---------- 0 000083F1 1E push ds 0 000083F2 06 push es 0 000083F3 1F pop ds 0 000083F4 07 pop es 1283 <1> 0 000083F5 E827FC call clear_info_fcb ; initialise to blanks and drive AL 1285 <1> 0 000083F8 BA[2800] mov dx,offset info_fcb ; use a scratch fcb 0 000083FB 89D7 mov di,dx ; dx saves initial di 0 000083FD 47 inc di 1289 <1> 0 000083FE 8B04 mov ax,[si] ; check first two chars 0 00008400 3C2E cmp al,'.' ; special case: if name = '.' 0 00008402 750E jne parse_path20 ; then we parse it differently 0 00008404 A4 movsb ; copy the '.' 0 00008405 80FC2E cmp ah,'.' ; special case: if name = '..' 0 00008408 7501 jne parse_path10 ; then we parse it differently 0 0000840A A4 movsb ; copy '..' 1297 <1> parse_path10: 0 0000840B AC lodsb ; get next char 0 0000840C 3C20 cmp al,' ' ; skip all spaces 0 0000840E 74FB je parse_path10 0 00008410 EB55 jmp parse_path50 ; now exit as normal 1302 <1> 1303 <1> parse_path20: 0 00008412 E8B700 call check_delim ; if first char = delimeter 0 00008415 7425 je parse_path30 ; then only allow '\' 1306 <1> 1307 <1> ; filename begins with a legal char, parse it normally 1308 <1> 0 00008417 89D7 mov di,dx 0 00008419 47 inc di ; di -> fcb name field 0 0000841A B90800 mov cx,8 ; length of name field 0 0000841D E87B00 call parse_one ; parse just the name 0 00008420 720C jc parse_path_not_lfn_asterisk 0 00008422 36803E[0000]00 cmp byte [ss:lfnpathflag], 0 0 00008428 7404 je parse_path_not_lfn_asterisk 0 0000842A 4E dec si 0 0000842B 4E dec si ; -> asterisk 0 0000842C B02E mov al, '.' 1319 <1> parse_path_not_lfn_asterisk: 1320 <1> 0 0000842E 89D7 mov di,dx ; DI -> FCB 0 00008430 26807D01E5 cmp byte ptr [es:1 + di],0E5h ; is first character E5? 0 00008435 7505 jne parse_path30 ; skip if not 0 00008437 26C6450105 mov byte ptr [es:1 + di],05h ; else make it internal synonym 1325 <1> parse_path30: 0 0000843C 3C2E cmp al,'.' 0 0000843E 7509 jne parse_path40 ; skip if no extension 0 00008440 83C709 add di,9 ; di -> fcb ext field 0 00008443 B90300 mov cx,3 ; length of ext field 0 00008446 E85200 call parse_one ; parse just extension 1331 <1> parse_path40: 1332 <1> %ifdef PASSWORD 0 00008449 3C3B cmp al,';' ; check if password specified 0 0000844B 751A jne parse_path50 ; skip if no password 0 0000844D BF[7200] mov di,offset password_buffer 0 00008450 B90800 mov cx,8 ; length of password field 0 00008453 E84500 call parse_one ; parse just password 0 00008456 50 push ax 0 00008457 1E push ds 0 00008458 56 push si 0 00008459 16 push ss 0 0000845A 1F pop ds ; DS:SI -> ASCII password 0 0000845B BE[7200] mov si,offset password_buffer 0 0000845E E8C006 call hash_pwd ; AX = encrypted password 0 00008461 A3[7000] mov [local_password],ax ; remember it in case we need it 0 00008464 5E pop si 0 00008465 1F pop ds 0 00008466 58 pop ax 1349 <1> %endif 1350 <1> parse_path50: 0 00008467 84C0 test al,al ; a NUL is OK 0 00008469 742B jz parse_path90 0 0000846B E89B00 call check_slash ; if terminator != '\' or '/', 0 0000846E F9 stc ; assume an error 0 0000846F 7524 jne parse_path80 ; report it if so 1356 <1> parse_path60: 0 00008471 AC lodsb ; get next character 0 00008472 E85700 call check_delim ; we expect a normal character 0 00008475 751E jne parse_path80 ; here - exit if we've got one 0 00008477 E88F00 call check_slash ; swallow '\'s at this point and leave 0 0000847A 74F5 je parse_path60 ; other delimiters for next time 0 0000847C 3C2E cmp al,'.' ; trailing '\.' ? 0 0000847E 7512 jne parse_path75 0 00008480 89F1 mov cx,si ; remember position of '.' 1365 <1> parse_path70: 0 00008482 AC lodsb ; now discard trailing spaces 0 00008483 3C20 cmp al,' ' 0 00008485 74FB je parse_path70 ; keep going until we lose all spaces 0 00008487 84C0 test al,al ; stop at a NUL 0 00008489 74DC jz parse_path50 0 0000848B E87B00 call check_slash ; if it's a '\' try again 0 0000848E 74D7 je parse_path50 0 00008490 89CE mov si,cx ; retract to the '.' 1374 <1> parse_path75: 0 00008492 B05C mov al,'\' ; return '\' as the delimiter 0 00008494 F8 clc ; and exit with no problems 1377 <1> parse_path80: 0 00008495 4E dec si ; retract a byte (CY unaffected) 1379 <1> parse_path90: 0 00008496 1E push ds 0 00008497 06 push es 0 00008498 1F pop ds 0 00008499 07 pop es 0 0000849A C3 ret 1385 <1> 1386 <1> 1387 <1> 1388 <1> Public parse_one 1389 <1> 1390 <1> ; Parse a single name or extension 1391 <1> ; On Entry: 1392 <1> ; DS:SI -> asciiz name 1393 <1> ; ES:DI -> start of fcb field 1394 <1> ; CX = field size 1395 <1> ; On Exit: 1396 <1> ; AL = last char parsed 1397 <1> ; 1398 <1> ; nb. make no assumptions about DS and ES 1399 <1> ; 1400 <1> 1401 <1> parse_one: 0 0000849B AC lodsb ; grab asciiz char 0 0000849C 3C2A cmp al,'*' ; if char = *, then fill 0 0000849E 7407 jz parse_one_wild ; rest of field with '?' 0 000084A0 E82900 call check_delim ; if char is not delimiter, 0 000084A3 750E jnz parse_one_char ; then move it to fcb 0 000084A5 F9 stc 0 000084A6 C3 ret ; if delimiter, return 1409 <1> 1410 <1> parse_one_wild: 0 000084A7 B03F mov al,'?' 0 000084A9 F3AA rep stosb ; after filling 0 000084AB 803C00 cmp byte ptr [si], 0 0 000084AE 7512 jne parse_one_ignore_no_asterisk 0 000084B0 F8 clc 0 000084B1 EB10 jmp parse_one_ignore ; skip until a delimiter 1417 <1> 1418 <1> parse_one_char: 1419 <1> %ifdef KANJI 0 000084B3 E809F9 call dbcs_lead ; is it 1st byte of Kanji pair? 0 000084B6 7507 jnz parse_one_skip ; skip if straight 8-bit 0 000084B8 46 inc si ; assume both chars discarded 0 000084B9 49 dec cx ; we will copy 2 bytes 0 000084BA E306 jcxz parse_one_ignore_no_asterisk 1425 <1> ; ignore both if only room for one 0 000084BC AA stosb ; thats the first byte 0 000084BD 4E dec si ; point at 2nd again 0 000084BE AC lodsb ; get the 2nd byte 1429 <1> parse_one_skip: 1430 <1> %endif 0 000084BF AA stosb ; send char to fcb 0 000084C0 E2D9 loop parse_one ; get another character from ASCIIZ string 1433 <1> 1434 <1> parse_one_ignore_no_asterisk: 0 000084C2 F9 stc 1436 <1> parse_one_ignore: 0 000084C3 9C pushf 1438 <1> parse_one_ignore_loop: 0 000084C4 AC lodsb 0 000084C5 E80400 call check_delim ; ignore up to next delimiter 0 000084C8 75FA jnz parse_one_ignore_loop 0 000084CA 9D popf 0 000084CB C3 ret 1444 <1> 1445 <1> ; 1446 <1> ; 1447 <1> ; Check for a path name delimiter 1448 <1> ; entry: AL = ASCIIZ char 1449 <1> ; exit: all registers preserved 1450 <1> ; ZF = 1 if char is a delimeter 1451 <1> ; ZF = 0 if char is legal in file names 1452 <1> 1453 <1> Public check_delim 1454 <1> 1455 <1> check_delim: 1456 <1> ;----------- 0 000084CC 3C20 cmp al,' ' ; if any printable char, 0 000084CE 7303 jae check_delim_char ; then skip 0 000084D0 38C0 cmp al,al ; set zf 0 000084D2 C3 ret 1461 <1> 1462 <1> check_delim_char: 1463 <1> %ifdef KANJI 0 000084D3 E8E9F8 call dbcs_lead ; if it's 1st of kanji pair 0 000084D6 7503 jne check_delim10 ; DON'T upper case it 0 000084D8 84C0 test al,al ; clear zf 0 000084DA C3 ret ; (should really check the 2nd byte) 1468 <1> check_delim10: 1469 <1> %endif 0 000084DB E83300 call toupper ; make it upper case 0 000084DE 06 push es 0 000084DF 57 push di 0 000084E0 51 push cx 0 000084E1 0E push cs 0 000084E2 07 pop es 0 000084E3 8D3E[AC17] lea di,[delim_string] ; es:di -> delimeters 0 000084E7 B90E00 mov cx,lengthof_delim_string 0 000084EA FC cld 0 000084EB F2AE repnz scasb ; match al against the list 0 000084ED 59 pop cx 0 000084EE 5F pop di 0 000084EF 07 pop es 0 000084F0 F8 clc ; never return cf set 0 000084F1 C3 ret ; with zf set by scasb 1485 <1> 0 000084F2 3A2E3B2C3D2B5C3C3E delim_string db ':.;,=+\<>|/"[]' ; DOS delimeters 0 000084FB 7C2F225B5D 1487 <1> lengthof_delim_string equ $ - delim_string 1488 <1> 1489 <1> 1490 <1> ; Check AX for '\\' 1491 <1> 1492 <1> Public check_dslash 1493 <1> 1494 <1> check_dslash: 0 00008500 86C4 xchg al,ah 0 00008502 E80400 call check_slash 0 00008505 86C4 xchg al,ah 0 00008507 7506 jne check_slash_done 1499 <1> ; jmp check_slash 1500 <1> 1501 <1> ; Check delimeter character for '\' or '/' 1502 <1> ; entry: al = char 1503 <1> ; exit: zf = 1 if either slash 1504 <1> 1505 <1> check_slash: 0 00008509 3C5C cmp al,'\' ; if first char is a backslash 0 0000850B 7402 jz check_slash_done ; or a frontslash, then 0 0000850D 3C2F cmp al,'/' ; return with zf set 1509 <1> check_slash_done: 0 0000850F F8 clc ; never return cf set 0 00008510 C3 ret 1512 <1> 1513 <1> ; Convert character to upper case 1514 <1> ; WARNING - may be called with DS <> SYSDAT 1515 <1> 1516 <1> toupper: 1517 <1> ;------- 0 00008511 84C0 test al,al 0 00008513 780B js toupper_intl 0 00008515 3C61 cmp al,'a' 0 00008517 7206 jb isupper 0 00008519 3C7A cmp al,'z' 0 0000851B 7702 ja isupper 0 0000851D 2C20 sub al,'a'-'A' 1525 <1> isupper: 0 0000851F C3 ret 1527 <1> 1528 <1> toupper_intl: 0 00008520 36FF1E[0000] call far [ss:intl_xlat] ; call international upper case vector 0 00008525 C3 ret 1531 <1> 1532 <1> kill_file: ; release clusters for file/dir and delete entry 1533 <1> ;--------- 0 00008526 E8[0000] call del_lfn ; delete any preceding LFN entries 0 00008529 8B1E[0000] mov bx,[dirp] ; get pointer to directory entry 1536 <1> %ifdef DELWATCH 0 0000852D E89EFD call hdsblk ; AX = directory root cluster 0 00008530 92 xchg ax,dx ; DX = dir cluster 0 00008531 8B0E[0000] mov cx,[dcnt] ; CX = directory index for entry 0 00008535 B402 mov ah,DELW_DELETE ; we are about to delete this dir 0 00008537 A0[0000] mov al,[physical_drv] ; directory entry so give delwatch 0 0000853A 36FF1E[0000] call far [ss:fdos_stub] ; a chance to make it pending delete 0 0000853F 7319 jnc kill_file10 ; delwatch took it - just update dir 1544 <1> %endif 0 00008541 B0E5 mov al,0E5h ; deleted file mark 0 00008543 8607 xchg al,[DNAME + bx] ; delete the directory entry 0 00008545 88470D mov [DUNDEL + bx],al ; save 1st letter for UNDEL command 0 00008548 8B471A mov ax,[DBLOCK1 + bx] ; get starting block # 0 0000854B 31D2 xor dx,dx 0 0000854D 833E[0000]00 cmp word [dosfat],FAT32 ; FAT32 file system? 0 00008552 7503 jne kill_file05 ; no 0 00008554 8B5714 mov dx,[DBLOCK1H + bx] ; else get high word of starting cluster 1553 <1> kill_file05: 0 00008557 E8[0000] call delfat ; release all clusters 1555 <1> kill_file10: 0 0000855A E9[0000] jmp flush_dirbuf ; update the directory 1557 <1> ; done it! (DIR/FAT still dirty) 1558 <1> 1559 <1> mustbe_nolbl: 1560 <1> ;------------ 1561 <1> ; On Entry: 1562 <1> ; None 1563 <1> ; On Exit: 1564 <1> ; Only returns if no label exists 1565 <1> ; forces us to root of drive 1566 <1> ; 0 0000855D 1E push ds 0 0000855E 07 pop es ; ES = DS for string ops 0 0000855F BE[2900] mov si,offset info_fcb+1 0 00008562 BF[3400] mov di,offset save_area ; SI->search name, DI->save area 0 00008565 B90B00 mov cx,11 0 00008568 57 push di ; save save_area 0 00008569 56 push si ; save info_fcb+1 0 0000856A 51 push cx ; save length 0 0000856B F3A4 rep movsb ; copy search name into save area 0 0000856D 59 pop cx ; CX = length (11) 0 0000856E 5F pop di ; DI = info_fcb+1 0 0000856F 57 push di 0 00008570 51 push cx 0 00008571 B03F mov al,'?' ; now fill info_fcb with wildcards 0 00008573 F3AA rep stosb 0 00008575 E80D00 call find_labelf ; look for a volume label 0 00008578 59 pop cx ; CX = length (11) 0 00008579 5F pop di ; DI = info_fcb+1 0 0000857A 5E pop si ; SI = save_area 0 0000857B 1E push ds 0 0000857C 07 pop es ; ES = DS for string ops 0 0000857D F3A4 rep movsb ; restore info_fcb 0 0000857F 7501 jnz mustbe_nolbl10 ; if we found a label bail out 0 00008581 C3 ret 1591 <1> mustbe_nolbl10: 0 00008582 E9DAE8 jmp fdos_ED_ACCESS ; return access denied 1593 <1> 1594 <1> find_labelf: ; find label only 1595 <1> ;----------- ; forces us to root 1596 <1> ; On Entry: 1597 <1> ; None 1598 <1> ; On Exit: 1599 <1> ; ZF clear if volume label found 1600 <1> ; dirp/dcnt tell where label is 1601 <1> ; 0 00008585 E8[0000] call setenddir ; start from beginning 1603 <1> ; jmp find_label 1604 <1> 1605 <1> find_label: ; find label only 1606 <1> ;---------- ; forces us to root 1607 <1> ; On Entry: 1608 <1> ; dcnt -> location to search from 1609 <1> ; On Exit: 1610 <1> ; ZF clear if volume label found 1611 <1> ; dirp/dcnt tell where label is 1612 <1> ; 0 00008588 C706[0000]0000 mov word [chdblk],0 ; don't assume sequential access 0 0000858E C706[0200]0000 mov word [chdblk+2],0 0 00008594 C706[0C00]0000 mov word [fdos_hds_blk],0 ; look for labels in the root 0 0000859A C706[0E00]0000 mov word [fdos_hds_blk+2],0 0 000085A0 C706[0000]FF00 mov word [finddfcb_mask],000ffh ; return VOL labels, not pending dels 1618 <1> find_label30: 0 000085A6 E8[0000] call finddfcb ; find matching file name 0 000085A9 740B jz find_label40 ; skip if not found 1621 <1> ; test DATTS[bx],DA_VOLUME 1622 <1> ; jz find_label30 ; try again if not a volume label 0 000085AB 8A470B mov al,[DATTS + bx] ; get attributes 0 000085AE 24DF and al,256-DA_RO-DA_ARCHIVE ; ignore read only and archive bits 0 000085B0 3C08 cmp al,DA_VOLUME ; is it a volume label? 0 000085B2 75F2 jnz find_label30 ; try again if not a volume label 0 000085B4 0C01 or al,01 ; clear ZF 1628 <1> find_label40: 0 000085B6 C706[0000]0008 mov word [finddfcb_mask],DA_VOLUME*256 0 000085BC C3 ret ; back to no VOL labels or pending dels 1631 <1> 1632 <1> %ifdef UNDELETE 1633 <1> find_pending_delete: ; find pending delete only 1634 <1> ;------------------- 1635 <1> ; On Entry: 1636 <1> ; dcnt -> location to search from 1637 <1> ; On Exit: 1638 <1> ; ZF clear if pending delete entry found 1639 <1> ; dirp/dcnt tell where entry is 1640 <1> ; 0 000085BD C706[0000]0000 mov word [finddfcb_mask],0h ; return pending delete entries 1642 <1> find_pending_delete10: 0 000085C3 B005 mov al,05h ; replace 1st char with 05h 0 000085C5 8606[2900] xchg al,[info_fcb+1] ; saving char we really want 0 000085C9 50 push ax 0 000085CA E8[0000] call finddfcb ; find matching file name 0 000085CD 58 pop ax 0 000085CE A2[2900] mov [info_fcb+1],al ; restore original 1st letter 0 000085D1 7420 jz find_pending_delete30 ; skip if not found 0 000085D3 F6470B08 test byte [DATTS + bx],DA_VOLUME ; Is it a pending delete entry 0 000085D7 74EA jz find_pending_delete10 ; No, try again if not a volume label 0 000085D9 837F1A00 cmp word ptr [DBLOCK1 + bx],0 ; Is this a pending delete entry 0 000085DD 74E4 jz find_pending_delete10 ; No, try again if not correct 0 000085DF 3C3F cmp al,'?' ; wildcard is OK 0 000085E1 7405 je find_pending_delete20 0 000085E3 3A470D cmp al,[DUNDEL + bx] ; does saved char match what we want? 0 000085E6 75DB jne find_pending_delete10 1658 <1> find_pending_delete20: 0 000085E8 80670BF7 and byte [DATTS + bx],~ DA_VOLUME ; mask out volume bit 0 000085EC 8A470D mov al,[DUNDEL + bx] ; move deleted character to normal 0 000085EF 8807 mov [DNAME + bx],al ; position for return 0 000085F1 08C0 or al,al ; clear the zero flag (assumes al!=0) 1663 <1> find_pending_delete30: 0 000085F3 C706[0000]0008 mov word [finddfcb_mask],DA_VOLUME*256 0 000085F9 C3 ret ; back to no VOL labels or pending dels 1666 <1> 1667 <1> %endif 1668 <1> 1669 <1> find_xfn: ; find spare external file number 1670 <1> ;-------- 1671 <1> ; exit: DI = new handle 1672 <1> 1673 <1> 0 000085FA 06 push es ; save ES while we play 0 000085FB 31FF xor di,di ; return handle 0 if don't have PSP 0 000085FD E8E102 call get_xftptr 0 00008600 720B jc fndxfn2 0 00008602 89FB mov bx,di ; save the offset 0 00008604 B0FF mov al,0FFh ; look for unused slot 0 00008606 F2AE repne scasb ; loop while CX != 0 and *ES:DI != 0FFh 0 00008608 7506 jne fndxfn3 ; ZF = 1 if match, else none found 0 0000860A 4F dec di ; DI = matching offset 0 0000860B 29DF sub di,bx ; DI = handle index 1684 <1> fndxfn2: 0 0000860D 07 pop es 0 0000860E F8 clc ; indicate no error 0 0000860F C3 ret 1688 <1> 1689 <1> fndxfn3: 0 00008610 07 pop es 0 00008611 F9 stc ; indicate an error 0 00008612 C3 ret 1693 <1> 1694 <1> Public alloc_dhndl 1695 <1> 1696 <1> alloc_dhndl: 1697 <1> ;----------- 1698 <1> ; provisionally allocate a spare DHNDL_, do not return without one 1699 <1> ; On Entry: 1700 <1> ; None 1701 <1> ; On Exit: 1702 <1> ; AX = IFN of handle 1703 <1> ; ES:BX -> DHNDL_ structure 1704 <1> ; (All other regs preserved) 0 00008613 E85B02 call find_dhndl ; try to find a spare DHNDL_ 0 00008616 7213 jc fdos_ED_HANDLE ; bail out if we can't 0 00008618 C3 ret 1708 <1> 1709 <1> mustbe_free_handle: 1710 <1> ;------------------ 1711 <1> ; return an error to user if either an XFN or an IFN is unavailable 1712 <1> ; On Entry: 1713 <1> ; None 1714 <1> ; On Exit: 1715 <1> ; None 1716 <1> ; 0 00008619 E8F7FF call alloc_dhndl ; make sure we can allocate a DHNDL 0 0000861C 26C7070000 mov word [es:DHNDL_COUNT + bx],0 ; free it in case open/creat fails 1719 <1> ; (we are protected by local_disk) 1720 <1> ; jmp alloc_xfn ; make sure an XFN is also free 1721 <1> 1722 <1> Public alloc_xfn 1723 <1> 1724 <1> alloc_xfn: ; find spare external file number 1725 <1> ;-------- 1726 <1> ; exit: DI = new handle 1727 <1> 0 00008621 E8D6FF call find_xfn ; try to find spare slot in XFT 0 00008624 7205 jc fdos_ED_HANDLE ; "out of handles" if no luck 0 00008626 893E[6C00] mov [fdos_ret],di ; else save the resulting handle 0 0000862A C3 ret 1732 <1> 1733 <1> 1734 <1> fdos_ED_HANDLE: 0 0000862B B8FCFF mov ax,ED_HANDLE ; out of user file #s, all 20 in use 0 0000862E E9F5E7 jmp fdos_error 1737 <1> 1738 <1> 1739 <1> ; Allocate & initialize file handle: 1740 <1> ; entry: AX = open mode 1741 <1> ; DIRP -> directory entry 1742 <1> ; exit: ES:BX = CURRENT_DHNDL = file handle 1743 <1> ; AX = fdos_ret = IFN 1744 <1> ; -or- 1745 <1> ; System call fails with ED_HANDLE 1746 <1> 1747 <1> open_handle: 1748 <1> ;----------- 0 00008631 8B1E[0000] mov bx,[dirp] ; else get directory entry 0 00008635 F6470B01 test byte [DATTS + bx],DA_RO ; check if file is r/o - if so 0 00008639 7403 jz creat_handle ; make handle r/o too 0 0000863B 83E0F0 and ax,~ DHM_RWMSK 1753 <1> creat_handle: 1754 <1> ;------------ 1755 <1> ; entry point for create file - when you create a read-only file 1756 <1> ; you still get a handle you can write with ! 0 0000863E 50 push ax ; save open mode 0 0000863F 96 xchg ax,si ; SI = open mode 0 00008640 BF1C00 mov di,S_OM_COMPAT ; check if open/sharing modes are compatible 0 00008643 E8EC01 call check_with_share ; does SHARE approve ? 0 00008646 E8CAFF call alloc_dhndl ; allocate a DHNDL_ structure 0 00008649 A3[6C00] mov [fdos_ret],ax ; remember IFN in case it's FCB 0 0000864C 5A pop dx 0 0000864D 52 push dx ; DX = open mode 0 0000864E 06 push es 0 0000864F 53 push bx ; save DHNDL_ pointer 0 00008650 F6C680 test dh,DHM_FCB/100h ; FCB call? 0 00008653 750F jne creat_handle10 ; skip XFN allocation if FCB 0 00008655 50 push ax ; save IFN 0 00008656 E8C8FF call alloc_xfn ; allocate spare XFN 0 00008659 58 pop ax ; recover IFN 0 0000865A 89FB mov bx,di ; BX = XFN 0 0000865C E88202 call get_xftptr ; ES:DI -> user file table 0 0000865F 7203 jc creat_handle10 ; skip if we don't have one 0 00008661 268801 mov [es:di+bx],al ; set IFN in PSP 1776 <1> creat_handle10: 0 00008664 5B pop bx 0 00008665 07 pop es 0 00008666 8D3F lea di,[DHNDL_COUNT + bx] ; point at open count 0 00008668 B80100 mov ax,1 0 0000866B AB stosw ; open by one 0 0000866C 58 pop ax ; recover open mode 0 0000866D B94040 mov cx,DHAT_TIMEOK+DHAT_CLEAN 0 00008670 A880 test al,DHM_LOCAL ; is it private ? 0 00008672 7405 jz creat_handle20 0 00008674 80CD10 or ch,DHAT_LOCAL/256 ; rememmber it's local 0 00008677 247F and al,~ DHM_LOCAL ; clear inherit bit 1788 <1> creat_handle20: 1789 <1> ; lea di,DHNDL_MODE[bx] ; update the mode 0 00008679 AB stosw 0 0000867A 8B36[0000] mov si,[dirp] 0 0000867E 8A440B mov al,[DATTS + si] ; get file attribute byte 0 00008681 8D7F04 lea di,[DHNDL_DATRB + bx] ; now copy file attribute 0 00008684 AA stosb ; to DHNDL_ 0 00008685 91 xchg ax,cx ; AX = attributes 0 00008686 0A06[0000] or al,[physical_drv] ; get physical drive 1797 <1> ; lea di,DHNDL_WATTR[bx] ; make as clean disk file 0 0000868A AB stosw 1799 <1> ; lea di,DHNDL_DEVOFF[bx] ; ES:DI -> dd entry in DHNDL_ 0 0000868B 36A1[0000] mov ax,word ptr [ss:current_ddsc] 0 0000868F AB stosw ; point to DDSC_ 0 00008690 36A1[0200] mov ax,word ptr [ss:current_ddsc+2] 0 00008694 AB stosw 0 00008695 8B441A mov ax,[DBLOCK1 + si] ; get starting cluster of file 1805 <1> ; lea di,DHNDL_BLK1[bx] 0 00008698 AB stosw 0 00008699 31C0 xor ax,ax 0 0000869B 833E[0000]00 cmp word [dosfat],FAT32 ; is this a FAT32 file system? 0 000086A0 7503 jne creat_handle25 ; no, then skip 0 000086A2 8B4414 mov ax,[DBLOCK1H + si] ; high word of cluster 1811 <1> creat_handle25: 0 000086A5 8D7F3B lea di,[DHNDL_BLK1H + bx] 0 000086A8 AB stosw 0 000086A9 8D7F43 lea di,[DHNDL_SIZEX + bx] ; FAT+ extended file size bits 0 000086AC 8A440C mov al,[DSIZEX + si] 0 000086AF 88C4 mov ah,al 0 000086B1 2407 and al,00000111b 0 000086B3 80E4E0 and ah,11100000b 0 000086B6 D0EC shr ah,1 0 000086B8 D0EC shr ah,1 0 000086BA 08E0 or al,ah 0 000086BC 30E4 xor ah,ah 0 000086BE AB stosw 0 000086BF 31C0 xor ax,ax 0 000086C1 AB stosw ; zero higher file size bits 0 000086C2 AB stosw 0 000086C3 AB stosw ; also the high dword of the position 0 000086C4 8D7416 lea si,[DTIME + si] 0 000086C7 8D7F0D lea di,[DHNDL_TIME + bx] 0 000086CA A5 movsw ; copy the time 1831 <1> ; lea di,DHNDL_DATE[bx] 0 000086CB A5 movsw ; and the date 0 000086CC AD lodsw ; skip 1st cluster (already done) 1834 <1> ; lea di,DHNDL_SIZE[bx] 0 000086CD A5 movsw 0 000086CE A5 movsw ; copy the file size 1837 <1> ; lea di,DHNDL_POS[bx] 0 000086CF 31C0 xor ax,ax ; zero current position 0 000086D1 AB stosw 0 000086D2 AB stosw 1841 <1> ; lea di,DHNDL_IDX[bx] 0 000086D3 AB stosw ; zero block index 0 000086D4 8D7F3D lea di,[DHNDL_IDXH + bx] 0 000086D7 AB stosw 0 000086D8 E8F3FB call hdsblk ; get directory block 0 000086DB 8D7F1B lea di,[DHNDL_DBLK + bx] 0 000086DE AB stosw 0 000086DF 89D0 mov ax,dx 0 000086E1 8D7F3F lea di,[DHNDL_DBLKH + bx] 0 000086E4 AB stosw 0 000086E5 A1[0000] mov ax,[dcnt] ; set DCNT of file 0 000086E8 8D7F1F lea di,[DHNDL_DCNTLO + bx] 0 000086EB AA stosb ; store low byte of DCNT 0 000086EC 2688671E mov [es:DHNDL_DCNTHI + bx],ah ; and hi byte 0 000086F0 8D7F20 lea di,[DHNDL_NAME + bx] ; copy name from dir entry 0 000086F3 8B36[0000] mov si,[dirp] 0 000086F7 B90B00 mov cx,11 0 000086FA F3A4 rep movsb 0 000086FC 31C0 xor ax,ax 0 000086FE AB stosw ; zero DWORD 0 000086FF AB stosw 0 00008700 8D7F33 lea di,[DHNDL_SHARE + bx] ; zero sharing record 0 00008703 AB stosw 0 00008704 AB stosw 0 00008705 AB stosw 0 00008706 AB stosw ; zero DHNDL_BLK + IFS 0 00008707 8D7F41 lea di,[DHNDL_BLKH + bx] 0 0000870A AB stosw 0 0000870B 36FF1E[1400] call far [ss:share_stub+S_OPEN] ; we have opened this handle 1870 <1> ; ask SHARE to register it 0 00008710 7204 jc create_handle30 0 00008712 A1[6C00] mov ax,[fdos_ret] ; AX = handle to return 0 00008715 C3 ret 1874 <1> create_handle30: ; free the handle again 0 00008716 50 push ax 0 00008717 A1[6C00] mov ax,[fdos_ret] 0 0000871A E8D700 call release_handle2 0 0000871D 58 pop ax 0 0000871E E905E7 jmp fdos_error 1880 <1> 1881 <1> 1882 <1> 1883 <1> Public verify_handle 1884 <1> 1885 <1> verify_handle: 1886 <1> ;------------- 1887 <1> ; On Exit: 1888 <1> ; ES:BX = DHNDL_ 1889 <1> ; CY set if bad file handle (nb. device handle is bad) 1890 <1> ; 0 00008721 E82000 call check_handle ; make sure we can access it 0 00008724 721D jc vfy_hnd9 ; return if character device 1893 <1> 1894 <1> select_handle: ; select directory of current handle 1895 <1> ;------------- 1896 <1> ; On Entry: 1897 <1> ; ES:BX -> DHNDL_ 1898 <1> ; On Exit: 1899 <1> ; ES:BX preserved 1900 <1> ; 0 00008726 268A4705 mov al,[es:DHNDL_ATTR + bx] ; get physical drive 0 0000872A 241F and al,DHAT_DRVMSK ; from attrib field 0 0000872C 06 push es 0 0000872D 53 push bx 0 0000872E E8[0000] call select_physical_drv ; select the drive 0 00008731 5B pop bx 0 00008732 07 pop es 0 00008733 268B471B mov ax,[es:DHNDL_DBLK + bx] 0 00008737 268B573F mov dx,[es:DHNDL_DBLKH + bx] 0 0000873B A3[0C00] mov [fdos_hds_blk],ax ; copy HDS_BLK 0 0000873E 8916[0E00] mov [fdos_hds_blk+2],dx 0 00008742 F8 clc ; handle is OK file 1913 <1> vfy_hnd9: 0 00008743 C3 ret ; good handle 1915 <1> 1916 <1> 1917 <1> ; Checks if parameter is a legal file handle: 1918 <1> ; Entry: CURRENT_DHNDL = handle to verify 1919 <1> ; Exit: ES:BX = DHNDL_ if O.K. 1920 <1> ; CY clear if local disk file 1921 <1> ; CY set if device/network handle 1922 <1> ; Note: doesn't return on error 1923 <1> 1924 <1> Public check_handle 1925 <1> check_handle: 1926 <1> ;------------ 0 00008744 C41E[0000] les bx,[current_dhndl] 0 00008748 26F747058080 test word [es:DHNDL_WATTR + bx],DHAT_REMOTE+DHAT_DEV 0 0000874E F9 stc ; assume device/network file 0 0000874F 7507 jnz chkhnd10 ; return with CY = 0 if disk file 0 00008751 36FF1E[0400] call far [ss:share_stub+S_UPDATE] ; make sure DHNDL_ info valid 0 00008756 7201 jc chkhnd20 ; if not close it down 1933 <1> chkhnd10: 0 00008758 C3 ret 1935 <1> 1936 <1> chkhnd20: 0 00008759 E88501 call get_xftptr ; ES:BX -> XFT 0 0000875C 7208 jc fdos_ED_H_MATCH ; skip if not handle 0 0000875E 8B1E[6000] mov bx,[fdos_pb+2] ; get XFN so we can poke 0 00008762 26C601FF mov byte ptr [es:di+bx],0ffh 1941 <1> ; PSP handle to closed 1942 <1> ; jmp fdos_ED_H_MATCH ; return "invalid handle" 1943 <1> 1944 <1> fdos_ED_H_MATCH: 0 00008766 B8FAFF mov ax,ED_H_MATCH ; "invalid handle" 0 00008769 E9BAE6 jmp fdos_error ; return an error 1947 <1> 1948 <1> public vfy_dhndl_ptr 1949 <1> public vfy_dhndl_ptr_AX 1950 <1> 1951 <1> vfy_dhndl_ptr: 1952 <1> ;============= 1953 <1> ; Verifies file handles at FDOS_xxxx calling level 1954 <1> ; before MXdisk is locked. 1955 <1> ; On Entry: 1956 <1> ; SS:BP -> func #, parm off, parm seg 1957 <1> ; stack holds two ret addresses + above values 1958 <1> ; On Exit: 1959 <1> ; ES:BX -> DHNDL_ 1960 <1> 0 0000876C 8B7602 mov si,[2 + bp] ; SI -> parameter block 0 0000876F 8B4402 mov ax,[2 + si] ; get file handle from parameter block 1963 <1> vfy_dhndl_ptr_AX: ; alternative entry point - AX=handle 0 00008772 36F606[0100]80 test byte [ss:remote_call+1],DHM_FCB/100h; if we are doing an FCB operation 0 00008778 7516 jnz vfy_dhndl10 ; deal only with IFN, forget PSP 0 0000877A 368E06[0000] mov es,[ss:current_psp] 0 0000877F 263B063200 cmp ax,[es:PSP_XFNMAX] ; CX = # entries in table 0 00008784 7363 jae vfy_dhndl_err 0 00008786 26C43E3400 les di,[es:PSP_XFTPTR] ; ES:DI -> user file table 0 0000878B 89C3 mov bx,ax ; get user file number (0-19) 0 0000878D 268A01 mov al,[es:bx+di] ; get IFN for this handle 1972 <1> vfy_dhndl10: 0 00008790 3CFF cmp al,0ffh ; invalid handle? 0 00008792 7455 je vfy_dhndl_err ; 00h-FEh only 0 00008794 36C41E[0000] les bx,[ss:file_ptr] ; get the address of the first entry 1976 <1> vfy_dhndl20: 0 00008799 263B4704 cmp ax,[es:DCNTRL_COUNT + bx] ; handle in this block? 0 0000879D 733E jae vfy_dhndl50 ; skip to try next block if not 0 0000879F B44B mov ah,DHNDL_LEN 0 000087A1 F6E4 mul ah 0 000087A3 83C006 add ax,DCNTRL_LEN ; skip the header 0 000087A6 01C3 add bx,ax ; add to start of structure 0 000087A8 268B0F mov cx,[es:DHNDL_COUNT + bx] ; fail if the handle is not in use 0 000087AB E33C jcxz vfy_dhndl_err 0 000087AD 41 inc cx ; FFFF = pre-allocated is also failed 0 000087AE 7439 jz vfy_dhndl_err 0 000087B0 36803E[0000]26 cmp byte [ss:WindowsHandleCheck],26h 1988 <1> ; have we been patched 0 000087B6 750A jne vfy_dhndl30 ; yes, don't check owner 0 000087B8 36A1[0000] mov ax,[ss:machine_id] ; get current process 0 000087BC 263B472F cmp ax,[es:DHNDL_UID + bx] ; are we the owning process 0 000087C0 7527 jne vfy_dhndl_err ; no, return an error 1993 <1> vfy_dhndl30: 0 000087C2 36891E[0000] mov word ptr [ss:current_dhndl],bx 0 000087C7 368C06[0200] mov word ptr [ss:current_dhndl+2],es 0 000087CC 26F747020020 test word [es:DHNDL_MODE + bx],DHM_NOCRIT 0 000087D2 7502 jnz vfy_dhndl40 ; are critical errors allowed ? 0 000087D4 F8 clc 0 000087D5 C3 ret 2000 <1> 2001 <1> vfy_dhndl40: 0 000087D6 800E[0000]40 or byte [valid_flg],NO_CRIT_ERRORS 0 000087DB F8 clc 0 000087DC C3 ret ; remember no critical errors possible 2005 <1> 2006 <1> vfy_dhndl50: 0 000087DD 262B4704 sub ax,[es:DCNTRL_COUNT + bx] ; update the internal file number 0 000087E1 26C41F les bx,[es:DCNTRL_DSADD + bx] ; get the next entry and check 0 000087E4 83FBFF cmp bx,0FFFFh ; for the end of the list 0 000087E7 75B0 jnz vfy_dhndl20 2011 <1> vfy_dhndl_err: 0 000087E9 83C402 add sp,2 ; pop return addr - return to caller 0 000087EC BBFAFF mov bx,ED_H_MATCH ; with "invalid handle" error 0 000087EF F9 stc 0 000087F0 C3 ret 2016 <1> 2017 <1> 2018 <1> 2019 <1> 2020 <1> ; On Entry: 2021 <1> ; FDOS_PB+2 = external file handle to release 2022 <1> ; On Exit: 2023 <1> ; ES:BX -> DHNDL_ 2024 <1> 2025 <1> release_handle: 2026 <1> ;-------------- 0 000087F1 A1[6000] mov ax,[fdos_pb+2] ; get user file number (0-19) 2028 <1> release_handle2: 2029 <1> ;--------------- 0 000087F4 E8EA00 call get_xftptr ; ES:DI -> XFN table 0 000087F7 720E jc release_ifn ; IFN = XFN if no PSP 0 000087F9 39C8 cmp ax,cx ; more than in handle table? 0 000087FB 730F jae rlshnd_err ; return error if too large 0 000087FD 93 xchg ax,bx ; BX = external file number 0 000087FE B0FF mov al,0FFh ; get old IFN, release XFN 0 00008800 268601 xchg al,[es:bx+di] ; get IFN for this handle 0 00008803 3CFF cmp al,0FFh 0 00008805 7405 je rlshnd_err 2039 <1> release_ifn: 0 00008807 E83E00 call ifn2dhndl ; ES:BX -> DHNDL_ 0 0000880A 7309 jnc check_no_dir_ret ; return if no error 2042 <1> 2043 <1> rlshnd_err: ; else bad handle 0 0000880C E957FF jmp fdos_ED_H_MATCH ; return the error 2045 <1> 2046 <1> 2047 <1> check_no_dir: ; check if entry is directory 2048 <1> ;-------- 2049 <1> ; entry: BX -> directory entry 2050 <1> 0 0000880F F6470B10 test byte [DATTS + bx],DA_DIR ; test if directory 0 00008813 7508 jnz chk_ro_err ; skip if a directory 2053 <1> check_no_dir_ret: 0 00008815 C3 ret ; else return to caller 2055 <1> 2056 <1> check_ro: ; check if file write protected 2057 <1> ;-------- 2058 <1> ; entry: BX -> directory entry 2059 <1> 0 00008816 F6470B01 test byte [DATTS + bx],DA_RO ; test if file r/o 0 0000881A 7501 jnz chk_ro_err ; skip if file r/o 0 0000881C C3 ret ; else return to caller 2063 <1> chk_ro_err: 0 0000881D E93FE6 jmp fdos_ED_ACCESS ; return "access denied" if r/o 2065 <1> 2066 <1> 2067 <1> 2068 <1> discard_files: ; discard all handles on adrive 2069 <1> ;------------- 0 00008820 A0[0000] mov al,[adrive] 0 00008823 36FF1E[1000] call far [ss:share_stub+S_DISCARD] ; tell share to forget about files 0 00008828 C3 ret 2073 <1> 2074 <1> 2075 <1> 2076 <1> ; Close file if it's us in compatibility modes 2077 <1> 2078 <1> close_if_same_psp: 2079 <1> ;----------------- 2080 <1> ; Note: We first check if the file is open by anyone other 2081 <1> ; than the same UID and PSP, or is open in shared mode. 2082 <1> ; In either case we deny the operation. 2083 <1> ; Otherwise we fall through and close the file. 2084 <1> ; We could do it in one with a new share, but this way means 2085 <1> ; less changes. 2086 <1> ; 0 00008829 BF2400 mov di,S_DENY_IF_OPEN ; check if file already open 0 0000882C E80300 call check_with_share ; and stop if it is 2089 <1> ; jmp close_if_open 2090 <1> 2091 <1> ; Make sure our file is not open 2092 <1> 2093 <1> close_if_open: 2094 <1> ;------------- 2095 <1> ; entry: HDSADR->BLK = block # of directory 2096 <1> ; HDSADR->DRV = drive number 2097 <1> ; DCNT = directory position 2098 <1> ; Note: If the file is open by any other process, 2099 <1> ; error ED_SHAREFAIL is returned from the system call 2100 <1> ; If open by us (same UID, any PSP) in compatibility mode, 2101 <1> ; close it and allow us to proceed. 2102 <1> 0 0000882F BF2000 mov di,S_CLOSE_IF_OPEN ; check if file already open 2104 <1> ; jmp check_with_share 2105 <1> 2106 <1> check_with_share: 2107 <1> ;---------------- 2108 <1> ; On Entry: 2109 <1> ; DI = S_ share query 2110 <1> ; On Exit: 2111 <1> ; Come back if share says it's OK. 2112 <1> ; 0 00008832 E899FA call hdsblk ; get directory block in AX 0 00008835 92 xchg ax,dx ; directory block 0 00008836 8B0E[0000] mov cx,[dcnt] ; get the directory count in CX 0 0000883A A0[0000] mov al,[physical_drv] ; get physical drive in AL 0 0000883D 36FF9D[0000] call far [ss:share_stub + di] ; ask SHARE if it knows of anyone open 0 00008842 7201 jc check_with_share10 0 00008844 C3 ret ; must be OK. 2120 <1> 2121 <1> check_with_share10: 0 00008845 E9DEE5 jmp fdos_error ; bail out with an error 2123 <1> 2124 <1> 2125 <1> 2126 <1> ; 2127 <1> ; Return a pointer to the DOS Handle corresponding to the internal 2128 <1> ; handle number passed in AX 2129 <1> ; 2130 <1> ; On Entry: 2131 <1> ; AL = IFN 2132 <1> ; 2133 <1> ; On Exit: 2134 <1> ; ES:BX -> DOS handle (All other Regs preserved) 2135 <1> ; CY set if no corresponding valid DHNDL_ 2136 <1> ; 2137 <1> Public ifn2dhndl 2138 <1> ifn2dhndl: 0 00008848 50 push ax 0 00008849 30E4 xor ah,ah ; make IFN a word 0 0000884B 36C41E[0000] les bx,[ss:file_ptr] ; get the address of the first entry 2142 <1> 2143 <1> ifn2dh10: 0 00008850 263B4704 cmp ax,[es:DCNTRL_COUNT + bx] ; handle in this block? 0 00008854 730C jae ifn2dh20 ; skip if not 0 00008856 B44B mov ah,DHNDL_LEN ; calculate offset of the DOS Handle 0 00008858 F6E4 mul ah 0 0000885A 01C3 add bx,ax ; add structure offset (should be 0) 0 0000885C 83C306 add bx,DCNTRL_LEN ; and then skip the header 0 0000885F 58 pop ax 0 00008860 F8 clc 0 00008861 C3 ret ; ES:BX -> valid DHDNL_ 2153 <1> 2154 <1> ifn2dh20: 0 00008862 262B4704 sub ax,[es:DCNTRL_COUNT + bx] ; update the internal file number 0 00008866 26C41F les bx,[es:DCNTRL_DSADD + bx] ; get the next entry and check 0 00008869 83FBFF cmp bx,0FFFFh ; for the end of the list 0 0000886C 75E2 jnz ifn2dh10 2159 <1> ifn2dh15: 0 0000886E 58 pop ax 0 0000886F F9 stc 0 00008870 C3 ret ; invalid file handle number 2163 <1> 2164 <1> 2165 <1> 2166 <1> ; 2167 <1> ; Allocate a DHNDL_ structure 2168 <1> ; 2169 <1> ; On Entry: 2170 <1> ; None 2171 <1> ; 2172 <1> ; On Exit: 2173 <1> ; CY clear if handle allocated 2174 <1> ; AX = IFN of handle 2175 <1> ; ES:BX -> DOS handle 2176 <1> ; (All other Regs preserved) 2177 <1> ; 2178 <1> Public find_dhndl 2179 <1> find_dhndl: 0 00008871 51 push cx 0 00008872 52 push dx 0 00008873 57 push di 0 00008874 56 push si 0 00008875 36A1[0000] mov ax,[ss:machine_id] ; get current process 0 00008879 368B16[0000] mov dx,[ss:owning_psp] ; DX = owining PSP 0 0000887E 31F6 xor si,si ; SI = IFN 0 00008880 36C43E[0000] les di,[ss:file_ptr] ; get the address of the first entry 2188 <1> find_dh10: 0 00008885 268B4D04 mov cx,[es:DCNTRL_COUNT + di] ; get # handles in this block 0 00008889 E327 jcxz find_dh40 ; skip if none 0 0000888B 8D5D06 lea bx,[DCNTRL_LEN + di] ; ES:BX -> 1st DHNDL_ 2192 <1> find_dh20: 0 0000888E 51 push cx 0 0000888F FA cli ; be alone while looking at handles 0 00008890 268B0F mov cx,[es:DHNDL_COUNT + bx] 0 00008893 E328 jcxz find_dh50 ; if handle free grab it 0 00008895 41 inc cx ; FFFF = allocated but unused 0 00008896 750C jnz find_dh30 0 00008898 263B472F cmp ax,[es:DHNDL_UID + bx] ; was it allocated to us 0 0000889C 7506 jne find_dh30 0 0000889E 263B5731 cmp dx,[es:DHNDL_PSP + bx] ; if so use it again 0 000088A2 7426 je find_dh60 2203 <1> find_dh30: 0 000088A4 FB sti ; finished with this handle 0 000088A5 59 pop cx 0 000088A6 46 inc si ; onto next IFN 0 000088A7 81FEFF00 cmp si,0FFh ; only handles 00-FE are valid 0 000088AB 730D jae find_dh45 ; so bail if out of range 0 000088AD 83C34B add bx,DHNDL_LEN ; onto next handle in the block 0 000088B0 E2DC loop find_dh20 2211 <1> find_dh40: 0 000088B2 26C43D les di,[es:DCNTRL_DSADD + di] ; get the next entry and check 0 000088B5 83FFFF cmp di,0FFFFh ; it's valid 0 000088B8 75CB jne find_dh10 2215 <1> find_dh45: 0 000088BA F9 stc ; no more handles, 0 000088BB EB1F jmp find_dh70 ; exit in failure.. 2218 <1> 2219 <1> find_dh50: 0 000088BD 26C707FFFF mov word [es:DHNDL_COUNT + bx],0FFFFh 0 000088C2 2689472F mov [es:DHNDL_UID + bx],ax ; allocate it to us 0 000088C6 26895731 mov [es:DHNDL_PSP + bx],dx 2223 <1> find_dh60: 0 000088CA FB sti ; safe again 0 000088CB 59 pop cx ; discard handle count 0 000088CC 96 xchg ax,si ; AX = IFN 0 000088CD 36891E[0000] mov word ptr [ss:current_dhndl],bx 0 000088D2 368C06[0200] mov word ptr [ss:current_dhndl+2],es 0 000088D7 36A3[0000] mov [ss:current_ifn],ax 0 000088DB F8 clc ; we have found and allocated a handle 2231 <1> find_dh70: 0 000088DC 5F pop di 0 000088DD 5E pop si 0 000088DE 5A pop dx 0 000088DF 59 pop cx 0 000088E0 C3 ret 2237 <1> 2238 <1> 2239 <1> Public get_xftptr 2240 <1> 2241 <1> get_xftptr: 2242 <1> ;---------- 2243 <1> ; On Entry: 2244 <1> ; None 2245 <1> ; On Exit: 2246 <1> ; ES:DI -> PSP_XFTPTR for current_psp 2247 <1> ; CX = # entries in it 2248 <1> ; CY set if not PSP operation (eg. FCB's) 2249 <1> ; (all other regs preserved) 2250 <1> ; 2251 <1> 0 000088E1 36F606[0100]80 test byte [ss:remote_call+1],DHM_FCB/100h; if we are doing an FCB operation 0 000088E7 7510 jnz get_xftptr_err ; deal only with IFN, forget PSP 0 000088E9 368E06[0000] mov es,[ss:current_psp] 0 000088EE 268B0E3200 mov cx,[es:PSP_XFNMAX] ; CX = # entries in table 0 000088F3 26C43E3400 les di,[es:PSP_XFTPTR] ; ES:DI -> user file table 0 000088F8 C3 ret 2258 <1> 2259 <1> get_xftptr_err: 0 000088F9 F9 stc ; forget about XFN's 0 000088FA C3 ret 2262 <1> 2263 <1> 2264 <1> Public current_dsk2al 2265 <1> 2266 <1> current_dsk2al: 2267 <1> ;-------------- 2268 <1> ; AL = current default drive 0 000088FB 36A0[0000] mov al,[ss:current_dsk] 0 000088FF C3 ret 2271 <1> 2272 <1> Public lds_si_dmaptr 2273 <1> 2274 <1> lds_si_dmaptr: 2275 <1> ;------------- 2276 <1> ; On Entry: 2277 <1> ; None 2278 <1> ; On Exit: 2279 <1> ; DS:SI -> current DMA address 2280 <1> ; (All other regs preserved) 0 00008900 36C536[0000] lds si,[ss:dma_offset] 0 00008905 C3 ret 2283 <1> 2284 <1> 2285 <1> public les_di_dmaptr 2286 <1> 2287 <1> les_di_dmaptr: 2288 <1> ;------------- 2289 <1> ; On Entry: 2290 <1> ; None 2291 <1> ; On Exit: 2292 <1> ; ES:DI -> current DMA address 2293 <1> ; (All other regs preserved) 0 00008906 36C43E[0000] les di,[ss:dma_offset] 0 0000890B C3 ret 2296 <1> 2297 <1> Public copy_asciiz 2298 <1> 2299 <1> copy_asciiz: 2300 <1> ;---------- 2301 <1> ; Copy an ASCIIZ string from DS:SI to ES:DI 0 0000890C AC lodsb 0 0000890D AA stosb 0 0000890E 84C0 test al,al 0 00008910 75FA jnz copy_asciiz 0 00008912 C3 ret 2307 <1> 2308 <1> %ifdef JOIN 2309 <1> 2310 <1> check_join: 2311 <1> ;---------- 2312 <1> ; On Entry: 2313 <1> ; fdos_hds -> HDS we wish to check 2314 <1> ; On Exit: 2315 <1> ; AH = drive (zero based) from fdos_hds_drv 2316 <1> ; AL = drive (zero based) of the JOIN root 2317 <1> ; if JOINed drive 2318 <1> ; ZF clear 2319 <1> ; else 2320 <1> ; ZF set 2321 <1> ; (All other regs presrved) 2322 <1> ; 0 00008913 06 push es 0 00008914 53 push bx 0 00008915 A0[1400] mov al,[fdos_hds_drv] ; get drive from HDS_ 0 00008918 88C4 mov ah,al ; save HDS_DRV in AH 0 0000891A 803E[0000]00 cmp byte [join_drv],0 ; need we do anything ? 0 0000891F 7446 je check_join30 ; not if we haven't JOIN'd 0 00008921 833E[1000]00 cmp word [fdos_hds_root],0 ; is virtual root the physical one ? 0 00008926 7539 jne check_join10 ; if not we can't be JOIN'd 0 00008928 833E[1200]00 cmp word [fdos_hds_root+2],0 0 0000892D 7532 jne check_join10 0 0000892F E8[0000] call get_ldt ; ES:BX -> LDT for this drive 0 00008932 722D jc check_join10 ; bad LDT - we can't be joined 0 00008934 26F747430020 test word [es:LDT_FLAGS + bx],LFLG_JOINED 0 0000893A 742B jz check_join30 0 0000893C 268A07 mov al,[es:LDT_NAME + bx] ; get drive letter 0 0000893F 2C41 sub al,'A' ; make drive letter zero based 0 00008941 8A1E[0A00] mov bl,byte ptr [path_drive] ; get the logical drive we are on 0 00008945 50 push ax 0 00008946 88D8 mov al,bl ; AL = logical drive we are using 0 00008948 E8[0000] call get_ldt ; ES:BX -> LDT for this drive 0 0000894B 58 pop ax 0 0000894C 7213 jc check_join10 ; no valid LDT.. 0 0000894E 26807F025C cmp byte [es:LDT_NAME+2 + bx],'\' ; are we at the root ? 0 00008953 750C jne check_join10 ; no, it can't be match 0 00008955 268A1F mov bl,[es:LDT_NAME + bx] ; get the root drive for this drive 0 00008958 80EB41 sub bl,'A' ; make drive letter zero based 0 0000895B 38D8 cmp al,bl ; are we on the JOIN'd drive ? 0 0000895D B3FF mov bl,0ffh ; assume we are 0 0000895F 7404 je check_join20 ; were we ? 2352 <1> check_join10: 0 00008961 88E0 mov al,ah ; restore HDS_DRV 0 00008963 30DB xor bl,bl ; return with ZF clear 2355 <1> check_join20: 0 00008965 84DB test bl,bl ; set ZF appropriately 2357 <1> check_join30: 0 00008967 5B pop bx 0 00008968 07 pop es 0 00008969 C3 ret 2361 <1> 2362 <1> offer_join: ; are we opening a JOIN'd drive ? 2363 <1> ;---------- 2364 <1> ; If we are at the root of a JOIN'd drive moving up ("..") fiddle HDS 2365 <1> ; onto parental JOIN drive root. 2366 <1> ; If we are at the root of a non-JOIN'd drive see if we are searching for 2367 <1> ; a JOIN'd drive directory 2368 <1> ; On Entry: 2369 <1> ; info_fcb = entry we are searching for 2370 <1> ; On Exit: 2371 <1> ; CY set if not a JOIN'd drive 2372 <1> ; 2373 <1> 0 0000896A 803E[0000]00 cmp byte [join_drv],0 ; need we do anything ? 0 0000896F 7502 jne oj_dochecks ; not, if we haven't JOIN'd 2376 <1> oj_rejected: 0 00008971 F9 stc ; not a JOIN drive 0 00008972 C3 ret 2379 <1> 2380 <1> oj_dochecks: 2381 <1> ;----------- 2382 <1> ; Before we do anything else we must be at the physical root of a drive 2383 <1> ; with a valid LDT. We then check for two cases 2384 <1> ; 1) Doing a '..' from a JOIN'd drive to it's parental root 2385 <1> ; 2) Opening a directory correpsonding to a JOIN'd drive 2386 <1> ; 0 00008973 A0[2800] mov al,[info_fcb] ; AL -> drive we are looking for 0 00008976 E8[0000] call get_ldt ; ES:BX -> LDT for this drive 0 00008979 72F6 jc oj_rejected ; bad LDT - we can't be joined 0 0000897B 26837F4F02 cmp word [es:LDT_ROOTLEN + bx],2 ; is root at top level ? 0 00008980 77EF ja oj_rejected ; no, skip the rest 0 00008982 833E[0C00]00 cmp word [fdos_hds_blk],0 ; are we at the root ? 0 00008987 75E8 jne oj_rejected ; if not we needn't do anything 2394 <1> 2395 <1> ; We have validated HDS_, so now check for case 1) 0 00008989 E887FF call check_join ; is it a joined drive ? 0 0000898C 740D jz oj_dir ; if not skip to case 2) 0 0000898E 813E[2900]2E2E cmp word [info_fcb+1],'..'; else is it a '..' in JOIN'd root? 0 00008994 75DB jne oj_rejected ; if not we needn't do anything 0 00008996 E88700 call mvhds_drvroot ; do '..' from root -> real root 0 00008999 F8 clc ; we handled it it ! 0 0000899A C3 ret 2403 <1> 2404 <1> oj_dir: 2405 <1> ;------ 2406 <1> ; We are in the physical root of a non-joined drive. We now need to see if 2407 <1> ; the dir we are searching for corresponds with a joined drive 2408 <1> ; 0 0000899B 56 push si 0 0000899C 57 push di 0 0000899D E84400 call build_match_name ; join_name = what we are looking for 0 000089A0 E80900 call look_for_match ; see if we can find it 0 000089A3 7204 jc oj_dir10 0 000089A5 E87800 call mvhds_drvroot ; we have a match - move into it 0 000089A8 F8 clc ; say we handled it 2416 <1> oj_dir10: 0 000089A9 5F pop di 0 000089AA 5E pop si 0 000089AB C3 ret 2420 <1> 2421 <1> 2422 <1> look_for_match: 2423 <1> ;-------------- 2424 <1> ; Compare join_name against available JOIN drives. 2425 <1> ; Return with CY clear if we found it, ES:BX -> LDT, AL the drive 0 000089AC 30ED xor ch,ch 0 000089AE 8A0E[0000] mov cl,[join_drv] ; search this many drives 0 000089B2 31C0 xor ax,ax ; start with drive A: 0 000089B4 8A26[0000] mov ah,[last_drv] 0 000089B8 E8[0000] call get_ldt ; ES:BX -> LDT for this drive 0 000089BB 730A jnc lfm20 0 000089BD C3 ret ; no LDT's... 2433 <1> lfm10: 0 000089BE FEC0 inc al ; next drive 0 000089C0 38E0 cmp al,ah ; paranioa - check if we have reached 0 000089C2 731E jae lfm50 ; last_drv and exit if so 0 000089C4 83C358 add bx,LDT_LEN ; next LDT 2438 <1> lfm20: 0 000089C7 26F747430020 test word [es:LDT_FLAGS + bx],LFLG_JOINED 0 000089CD 74EF jz lfm10 ; if not JOIN'd try next candidate 2441 <1> 0 000089CF 8D3F lea di,[LDT_NAME + bx] ; ES:DI -> JOIN info 0 000089D1 BE[7A00] mov si,offset join_name ; lets see if it matches the 0 000089D4 50 push ax 2445 <1> lfm30: 0 000089D5 AC lodsb ; get a byte 0 000089D6 AE scasb ; does it match ? 0 000089D7 7504 jne lfm40 ; no, forget it 0 000089D9 84C0 test al,al ; end of the string yet ? 0 000089DB 75F8 jnz lfm30 ; no, keep trying 2451 <1> lfm40: 0 000089DD 58 pop ax 0 000089DE 7403 je lfm60 ; did we match ? 0 000089E0 E2DC loop lfm10 ; no, if any JOIN's left try them 2455 <1> lfm50: 0 000089E2 F9 stc ; we didn't find it 2457 <1> lfm60: 0 000089E3 C3 ret 2459 <1> 2460 <1> build_match_name: 2461 <1> ;---------------- 2462 <1> ; Fill join_name with the "C:\JOIN" we want to find 2463 <1> ; 0 000089E4 A0[2800] mov al,[info_fcb] ; AL -> drive we are looking for 0 000089E7 FEC8 dec al ; make it zero based 0 000089E9 E8[0000] call get_ldt ; ES:BX -> LDT for this drive 0 000089EC 268A07 mov al,[es:LDT_NAME + bx] ; get the drive "D" 0 000089EF 1E push ds 0 000089F0 07 pop es ; ES -> SYSDAT 0 000089F1 BF[7A00] mov di,offset join_name ; construct the target name 0 000089F4 AA stosb ; plant the drive letter 0 000089F5 B83A5C mov ax,':\' ; NASM port swapped text literals 0 000089F8 AB stosw ; now we have "d:\" 0 000089F9 BB[2900] mov bx,offset info_fcb+1 ; DS:SI -> name we are looking for 0 000089FC E9E7F8 jmp unparse ; unparse the name 2476 <1> 2477 <1> 2478 <1> Public mv_join_root 2479 <1> 2480 <1> mv_join_root: 2481 <1> ;------------ 2482 <1> ; Poke the fdos_hds to be the root. If it's the physical root we then 2483 <1> ; see if it is a JOIN'd drive. If it is we poke the drive and reselect 2484 <1> ; the disk so we are at the real root of the drive. 2485 <1> ; 0 000089FF 53 push bx 0 00008A00 56 push si 0 00008A01 57 push di ; save index registers 0 00008A02 A1[1000] mov ax,[fdos_hds_root] 0 00008A05 8B16[1200] mov dx,[fdos_hds_root+2] 0 00008A09 A3[0C00] mov [fdos_hds_blk],ax ; move us to virtual root 0 00008A0C 8916[0E00] mov [fdos_hds_blk+2],dx 0 00008A10 85C0 test ax,ax ; is it the real root ? 0 00008A12 7508 jnz mvj_root10 ; if not forget about JOIN'd drives 0 00008A14 E8FCFE call check_join ; are we joined ? 0 00008A17 7403 jz mvj_root10 ; no, we've done enough 0 00008A19 E80400 call mvhds_drvroot ; make it real root 2498 <1> mvj_root10: 0 00008A1C 5F pop di 0 00008A1D 5E pop si 0 00008A1E 5B pop bx ; restore index registers 0 00008A1F C3 ret 2503 <1> 2504 <1> 2505 <1> mvhds_drvroot: 2506 <1> ;------------- 2507 <1> ; On Entry: 2508 <1> ; AL = Drive (0 based physical) 2509 <1> ; On Exit: 2510 <1> ; None 2511 <1> ; 2512 <1> ; Poke the HDS to be at the root of drive AL and select that drive 2513 <1> ; 0 00008A20 A2[1400] mov [fdos_hds_drv],al ; change to joined drive 0 00008A23 31D2 xor dx,dx 0 00008A25 8916[0C00] mov [fdos_hds_blk],dx ; put us back to the root again 0 00008A29 8916[0E00] mov [fdos_hds_blk+2],dx 0 00008A2D 8916[1000] mov [fdos_hds_root],dx 0 00008A31 8916[1200] mov [fdos_hds_root+2],dx 0 00008A35 3A06[0000] cmp al,[physical_drv] ; already there ? 0 00008A39 7403 je mvhds_drvroot10 ; then skip the selection 0 00008A3B E8[0000] call select_physical_drv ; select the drive 2523 <1> mvhds_drvroot10: 0 00008A3E E9D0F5 jmp path_prep_root ; info_fcb = '.' 2525 <1> ; ret 2526 <1> 2527 <1> %endif ;JOIN 2528 <1> 2529 <1> stamp_dir_entry: 2530 <1> ;--------------- 2531 <1> ; On Entry: 2532 <1> ; DIRP -> None 2533 <1> ; On Exit: 2534 <1> ; None 2535 <1> ; 2536 <1> ; Apply current date/time stamp to a directory, along with any other 2537 <1> ; security information required. 2538 <1> ; 2539 <1> %ifdef PASSWORD 0 00008A41 8B0E[7000] mov cx,[local_password] ; were we given a password ? 0 00008A45 E317 jcxz stamp_dir_entry10 ; if so apply it 0 00008A47 8B1E[0000] mov bx,[dirp] 0 00008A4B 833E[0000]00 cmp word [dosfat],FAT32 ; FAT32 file system? 0 00008A50 740C je stamp_dir_entry10 ; then do not overwrite this entry 0 00008A52 C74714DD0D mov word [DPWM + bx],PWM_ANY ; deny all for compatibility 0 00008A57 804F0B02 or byte [DATTS + bx],DA_HIDDEN ; make dir entry hidden 0 00008A5B 894F0E mov [DPWD + bx],cx ; with this password 2548 <1> stamp_dir_entry10: 2549 <1> %endif 0 00008A5E E81700 call ReadTOD ; get current time/dat 0 00008A61 8B1E[0000] mov bx,[dirp] 2552 <1> ; jmp stamp_date_and_time 2553 <1> stamp_date_and_time: 2554 <1> ; On Entry: 2555 <1> ; BX -> directory entry 2556 <1> ; AX = time 2557 <1> ; DX = date 2558 <1> ; On Exit: 2559 <1> ; None 2560 <1> ; stamp a directory entry with a given date and time 0 00008A65 895718 mov [DDATE + bx],dx 0 00008A68 894716 mov [DTIME + bx],ax 0 00008A6B B420 mov ah,PASSWD_CREAT ; call out to SECURITY TSR 0 00008A6D 36FF1E[0000] call far [ss:fdos_stub] 0 00008A72 7203 jc stamp_date_and_time10 0 00008A74 E9AFE3 jmp fdos_error ; return an error if required 2567 <1> stamp_date_and_time10: 0 00008A77 C3 ret 2569 <1> 2570 <1> 2571 <1> public ReadTOD 2572 <1> 2573 <1> ReadTOD: 2574 <1> ;------- 2575 <1> ; On Entry: 2576 <1> ; None 2577 <1> ; On Exit: 2578 <1> ; DX = internal date format 2579 <1> ; AX = internal time format 2580 <1> ; 0 00008A78 E8[0000] call ReadTimeAndDate ; get current time/date from BIOS 2582 <1> ; jmp GetTOD 2583 <1> 2584 <1> GetTOD: 2585 <1> ;------- 2586 <1> ; On Entry: 2587 <1> ; None 2588 <1> ; On Exit: 2589 <1> ; DX = internal date format 2590 <1> ; AX = internal time format 2591 <1> ; 0 00008A7B A1[0000] mov ax,[yearsSince1980] ; year is bits 9-15 0 00008A7E B104 mov cl,4 0 00008A80 D3E0 shl ax,cl 0 00008A82 0206[0000] add al,[month] ; month is bits 4-8 0 00008A86 B105 mov cl,5 0 00008A88 D3E0 shl ax,cl 0 00008A8A 0206[0000] add al,[dayOfMonth] ; day is bits 0-3 0 00008A8E 92 xchg ax,dx ; DX = date 2600 <1> 0 00008A8F A0[0000] mov al,[hour] ; hour is bits 11-15 0 00008A92 B106 mov cl,6 0 00008A94 D3E0 shl ax,cl 0 00008A96 0206[0000] add al,[minute] ; minute is bits 5-10 0 00008A9A B105 mov cl,5 0 00008A9C D3E0 shl ax,cl 0 00008A9E 8A0E[0000] mov cl,[second] ; second/2 is bits 0-4 0 00008AA2 D0E9 shr cl,1 ; 0 00008AA4 00C8 add al,cl 0 00008AA6 C3 ret 2611 <1> 2612 <1> 2613 <1> 2614 <1> select_from_DTA: 2615 <1> ;---------------- 2616 <1> ; called by search next/undelete/purge to select a disk and prepare for 2617 <1> ; a directory search based upon DTA contents. 2618 <1> ; 0 00008AA7 1E push ds 0 00008AA8 E855FE call lds_si_dmaptr ; DS:SI -> DMA address 0 00008AAB AC lodsb ; get search drive 0 00008AAC 1F pop ds 0 00008AAD 48 dec ax ; (stored 1-relative) 0 00008AAE A3[0A00] mov [path_drive],ax ; restore path drive 0 00008AB1 E8[0000] call select_physical_drv ; select the drive in AL 0 00008AB4 1E push ds 0 00008AB5 1E push ds 0 00008AB6 07 pop es ; ES = local segment 0 00008AB7 E846FE call lds_si_dmaptr ; DS:SI -> DMA address 0 00008ABA 46 inc si ; skip the drive # 0 00008ABB BF[2900] mov di,offset info_fcb+1 ; copy FCB back to INFO_FCB 0 00008ABE B90B00 mov cx,11 0 00008AC1 F3A4 rep movsb 2634 <1> 0 00008AC3 AC lodsb ; get search attribute 0 00008AC4 26A2[2700] mov [es:attributes],al 2637 <1> 0 00008AC8 AD lodsw ; get directory count 0 00008AC9 26A3[0000] mov [es:dcnt],ax 2640 <1> 0 00008ACD AD lodsw ; get the directory block 0 00008ACE 92 xchg ax,dx 0 00008ACF AD lodsw 0 00008AD0 92 xchg ax,dx 0 00008AD1 1F pop ds ; restore data segment 0 00008AD2 A3[0C00] mov [fdos_hds_blk],ax 0 00008AD5 8916[0E00] mov [fdos_hds_blk+2],dx 0 00008AD9 C3 ret 2649 <1> 2650 <1> %ifdef PASSWORD 2651 <1> 2652 <1> check_pwd_d: ; check if PW protected in any mode 2653 <1> ;----------- 0 00008ADA B81101 mov ax,PWM_D 0 00008ADD EB03 jmp check_pwd 2656 <1> 2657 <1> check_pwd_any: ; check if PW protected in any mode 2658 <1> ;------------- 0 00008ADF B8DD0D mov ax,PWM_ANY 2660 <1> ; jmp check_pwd 2661 <1> 2662 <1> check_pwd: ; check for password mismatch 2663 <1> ;--------- 2664 <1> ; entry: AX = password mode to be checked 2665 <1> ; DIRP -> directory entry for file 2666 <1> ; exit: BX, SI preserved 2667 <1> 0 00008AE2 50 push ax 0 00008AE3 53 push bx 0 00008AE4 8B1E[0000] mov bx,[dirp] ; BX -> file to be opened/deleted/etc. 0 00008AE8 91 xchg ax,cx ; password mode in CX 0 00008AE9 B422 mov ah,PASSWD_CHECK ; call out to SECURITY TSR 0 00008AEB 36FF1E[0000] call far [ss:fdos_stub] 0 00008AF0 7329 jnc check_pwd20 2675 <1> 0 00008AF2 31C0 xor ax,ax 0 00008AF4 833E[0000]00 cmp word [dosfat],FAT32 ; FAT32 filesystem? 0 00008AF9 7403 je check_pwd05 ; then assume no password set 0 00008AFB 8B470E mov ax,[DPWD + bx] ; get password hash code from entry 2680 <1> check_pwd05: 0 00008AFE E31E jcxz check_pwd10 ; exit if no password 0 00008B00 3B06[6E00] cmp ax,[global_password] ; compare with default password 0 00008B04 7418 je check_pwd10 ; yes, go ahead 0 00008B06 3B06[7000] cmp ax,[local_password] ; is it one we've just parsed ? 0 00008B0A 7412 je check_pwd10 ; yes, go ahead 2686 <1> ; else we've got a password mismatch 2687 <1> 0 00008B0C 833E[0000]00 cmp word [dosfat],FAT32 ; check if FAT32 file system 0 00008B11 740B je check_pwd10 ; if yes then passwords do not apply 0 00008B13 854F14 test cx,[DPWM + bx] ; test if password mode affects us 0 00008B16 7406 jz check_pwd10 ; skip if attempted access O.K. 0 00008B18 B8AAFF mov ax,ED_PASSWORD ; return password error 2693 <1> check_pwd20: 0 00008B1B E908E3 jmp fdos_error 2695 <1> 2696 <1> check_pwd10: 0 00008B1E 5B pop bx 0 00008B1F 58 pop ax 0 00008B20 C3 ret 2700 <1> 2701 <1> Public hash_pwd 2702 <1> 2703 <1> hash_pwd: ; compute 16-bit hash code for 1st COMMON_DMA password 2704 <1> ;-------- 2705 <1> ; On Entry: 2706 <1> ; DS:SI -> 8 character password 2707 <1> ; On Exit: 2708 <1> ; AX = password hash code or 0000 if none (ZF set) 2709 <1> ; SI corrupted, all other regs preserved 2710 <1> ; 2711 <1> 0 00008B21 51 push cx 0 00008B22 55 push bp 0 00008B23 B90800 mov cx,8 ; ch = 0, cl = 8 0 00008B26 89E5 mov bp,sp ; reverse and upper-case the name 0 00008B28 29CC sub sp,cx ; using temp buffer on the stack 0 00008B2A 31C0 xor ax,ax ; zero null password flag 2718 <1> 2719 <1> hash_pwd1: 0 00008B2C AC lodsb ; get next ASCII character 0 00008B2D E8E1F9 call toupper ; international upper case 0 00008B30 4D dec bp 0 00008B31 884600 mov [bp],al ; copy password char to encrypted buff 0 00008B34 08C0 or al,al ; is password char zero? 0 00008B36 7406 jz hash_pwd2 ; yes 0 00008B38 3C20 cmp al,' ' ; is password char blank? 0 00008B3A 7402 je hash_pwd2 ; yes 0 00008B3C FEC4 inc ah ; password is not null 2729 <1> hash_pwd2: 0 00008B3E 00C5 add ch,al ; add password char to encrypt CRC 0 00008B40 FEC9 dec cl 0 00008B42 75E8 jnz hash_pwd1 2733 <1> 0 00008B44 88E8 mov al,ch ; AL = password CRC 0 00008B46 B90800 mov cx,8 ; encrypt 8 characters 0 00008B49 08C4 or ah,al ; if CRC = 0 and all 00 or ' ' 0 00008B4B 7416 jz hash_pwd6 ; then there is no password 2738 <1> 2739 <1> hash_pwd3: 0 00008B4D 304600 xor [bp],al ; encrypt password on stack 0 00008B50 45 inc bp 0 00008B51 E2FA loop hash_pwd3 2743 <1> 0 00008B53 31ED xor bp,bp ; initialize hash code 0 00008B55 B90400 mov cx,4 ; 8 bytes = 4 words 2746 <1> hash_pwd4: 0 00008B58 58 pop ax ; get two encrypted characters 0 00008B59 D3C0 rol ax,cl ; juggle them about a bit 0 00008B5B 31C5 xor bp,ax ; "add" them into hash code 0 00008B5D E2F9 loop hash_pwd4 ; repeat for whole password 0 00008B5F 7501 jnz hash_pwd5 ; skip if result is non-zero 0 00008B61 45 inc bp ; else force it to be non-zero 2753 <1> hash_pwd5: 0 00008B62 95 xchg ax,bp ; return hash code in AX 2755 <1> hash_pwd6: 0 00008B63 01CC add sp,cx ; tidy up stack if buffer not poped 0 00008B65 85C0 test ax,ax ; set ZF flag appropriately 0 00008B67 5D pop bp 0 00008B68 59 pop cx 0 00008B69 C3 ret 2761 <1> 2762 <1> %endif 2763 <1> 2764 <1> 2765 <1> public share_delay 2766 <1> 2767 <1> ; waste time before retrying operation that failed due to SHARE intervention 2768 <1> share_delay: 0 00008B6A 36803E[0000]00 cmp byte [ss:remote_call],0 0 00008B70 7511 jne share_delay_30 0 00008B72 51 push cx 0 00008B73 368B0E[0000] mov cx,[ss:net_delay] 0 00008B78 E308 jcxz share_delay_20 2774 <1> share_delay_10: 0 00008B7A 51 push cx 0 00008B7B 31C9 xor cx,cx 0 00008B7D E2FE loop $ 0 00008B7F 59 pop cx 0 00008B80 E2F8 loop share_delay_10 2780 <1> share_delay_20: 0 00008B82 59 pop cx 2782 <1> share_delay_30: 0 00008B83 C3 ret 2784 <1> 2785 <1> BDOS_CODE ends 445 ;=== Pop trace listing source 446 === Switch to base=00C180h -> "BDOS_DATA" 447 section BDOS_DATA public align=2 class=DATA 447 ****************** warning: segment attributes specified on redeclaration of segment: ignoring [-w+other] 448 449 BDOS_DATA ends 450 451 END === Trace listing source: drdos/bin/cdevio.lst 1 ;title 'F_DOS Character device I/O' 2 ; File : $CDEVIO.ASM$ 3 ; 4 ; Description : 5 ; 6 ; Original Author : DIGITAL RESEARCH 7 ; 8 ; Last Edited By : $CALDERA$ 9 ; 10 ;-----------------------------------------------------------------------; 11 ; Copyright Work of Caldera, Inc. All Rights Reserved. 12 ; 13 ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, 14 ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. 15 ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES 16 ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF 17 ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO 18 ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE 19 ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE 20 ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, 21 ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, 22 ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, 23 ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF 24 ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT 25 ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND 26 ; CIVIL LIABILITY. 27 ;-----------------------------------------------------------------------; 28 ; 29 ; *** Current Edit History *** 30 ; *** End of Current Edit History *** 31 ; $Log: $ 32 ; CDEVIO.A86 1.18 94/12/21 11:16:29 33 ; Changed dev_dup to refuse from duplicating remote devices rather 34 ; than refuse from duplicating FCBs 35 ; Made open_dev return IFN rather than XFN for FCB opens 36 ; Made open_dev put the current time/date into DHNDL_TIME/DHNDL_DATE 37 ; CDEVIO.A86 1.16 94/10/07 09:00:18 38 ; Added patch 004 as source fix. Changed request header length for character 39 ; device to 16h. Used RH4_CDEV_LEN instead of RH4_LEN. 40 ; CDEVIO.A86 1.15 93/12/10 00:09:17 41 ; Move non-inherited bit to correct place in file handle 42 ; CDEVIO.A86 1.14 93/11/26 16:17:14 43 ; Update char_error so ES:SI -> device driver header itself; 44 ; ENDLOG 45 46 group PCMCODE BDOS_CODE 47 group PCMDATA BDOS_DATA PCMODE_DATA 48 49 ASSUME DS:PCMDATA 50 51 [list -] 61 === Switch to base=00C180h -> "PCMODE_DATA" 62 section PCMODE_DATA public align=2 class=DATA 63 extrn fdos_buf:byte ; caveat: in PCMODE data segment 64 PCMODE_DATA ends 65 === Switch to base=00C180h -> "BDOS_DATA" 66 section BDOS_DATA public align=2 class=DATA 67 extrn fdos_pb:word 68 extrn fdos_ret:word 69 BDOS_DATA ends 70 71 ; 72 ; Critical Error responses from the default INT 24 handler and 73 ; the DO_INT24 routine. 74 ; 75 ERR_IGNORE equ 0 ; Ignore Error 76 ERR_RETRY equ 1 ; Retry the Operation 77 ERR_ABORT equ 2 ; Terminate the Process 78 ERR_FAIL equ 3 ; Fail Function 79 === Switch to base=000000h -> "BDOS_CODE" 80 section BDOS_CODE public align=1 class=CODE 81 82 public open_dev 83 public close_dev 84 public dup_dev 85 public read_dev 86 public write_dev 87 public first_dev 88 public ioc6_dev 89 public ioc7_dev 90 91 extrn cooked_write:near ; write to cooked console 92 extrn read_line:near ; read edited line 93 extrn break_check:near ; look for CTRL C 94 extrn char_error:near ; generate Int 24 95 96 extrn current_dsk2al:near ; get default drive in AL 97 extrn device_driver:near 98 extrn alloc_dhndl:near ; find free DHNDL_ structure 99 extrn alloc_xfn:near 100 extrn les_di_dmaptr:near 101 extrn release_handle:near 102 extrn get_xftptr:near 103 extrn timestamp_dhndl:near 104 105 106 ; Character device functions 107 ; ========================== 108 109 open_dev: 110 ;-------- 111 ; Entry: ES:BX -> character device header 112 113 ; Note: We own the MXdisk here, fdos_pb -> parameter data 114 0 00008B84 06 push es 0 00008B85 53 push bx ; save device driver address 0 00008B86 E8[0000] call alloc_xfn ; DI = XFN 0 00008B89 57 push di ; save XFN 0 00008B8A E8[0000] call alloc_dhndl ; ES:BX -> DHNDL, AX = IFN 0 00008B8D 5A pop dx ; DX = XFN 0 00008B8E 96 xchg ax,si ; SI = IFN 0 00008B8F 31C0 xor ax,ax 0 00008B91 8D7F04 lea di,[DHNDL_DATRB + bx] ; point at start of area to fill 0 00008B94 B92B00 mov cx,DHNDL_UID-DHNDL_DATRB 0 00008B97 F3AA rep stosb 0 00008B99 8D7F43 lea di,[DHNDL_SIZEX + bx] 0 00008B9C B90400 mov cx,(DHNDL_LEN - DHNDL_SIZEX) / 2 0 00008B9F F3AB rep stosw ; clear 64-bit high dwords size/seek 0 00008BA1 26894733 mov [es:DHNDL_SHARE + bx],ax ; also zap share word 0 00008BA5 268F4707 pop word [es:DHNDL_DEVOFF + bx] 0 00008BA9 268F4709 pop word [es:DHNDL_DEVSEG + bx] ; save device driver address 132 0 00008BAD 56 push si 0 00008BAE 52 push dx ; save IFN/XFN 135 0 00008BAF 26C7070100 mov word [es:DHNDL_COUNT + bx],1 0 00008BB4 1E push ds 0 00008BB5 A1[0600] mov ax,[fdos_pb+6] ; AX = open mode 0 00008BB8 B9C040 mov cx,DHAT_DEV+DHAT_CLEAN+DHAT_TIMEOK 0 00008BBB 26C57707 lds si,[es:DHNDL_DEVPTR + bx] ; DS:SI -> device driver 141 DEVHDR.ATTRIB equ ATTRIB ; NASM port label 0 00008BBF 0A4C04 or cl,byte ptr [DEVHDR.ATTRIB + si] 143 ; get attrib from device driver 0 00008BC2 A880 test al,DHM_LOCAL ; is it private ? 0 00008BC4 7405 jz open_dev10 0 00008BC6 247F and al,~ DHM_LOCAL ; clear inherit bit 0 00008BC8 80CD10 or ch,DHAT_LOCAL/256 ; rememmber it's local 148 open_dev10: 0 00008BCB 26894702 mov [es:DHNDL_MODE + bx],ax 0 00008BCF 26894F05 mov [es:DHNDL_WATTR + bx],cx 151 DEVHDR.NAM equ NAM ; NASM port label 0 00008BD3 8D740A lea si,[DEVHDR.NAM + si] ; copy the device name 0 00008BD6 8D7F20 lea di,[DHNDL_NAME + bx] ; from the device header 0 00008BD9 B90400 mov cx,8/2 0 00008BDC F3A5 rep movsw 0 00008BDE B020 mov al,' ' 0 00008BE0 B103 mov cl,3 ; space the file extension 0 00008BE2 F3AA rep stosb 0 00008BE4 1F pop ds 160 0 00008BE5 5A pop dx 0 00008BE6 58 pop ax ; AX = IFN, DX = XFN 163 0 00008BE7 06 push es 0 00008BE8 E8[0000] call get_xftptr ; ES:DI -> PSP_XFTPTR for current_psp 0 00008BEB 7204 jc open_dev20 ; no PSP, skip updating XFN 0 00008BED 01D7 add di,dx ; ES:DI -> entry in PSP 0 00008BEF AA stosb ; update entry in PSP 0 00008BF0 92 xchg ax,dx 170 open_dev20: 0 00008BF1 07 pop es 172 0 00008BF2 A3[0000] mov [fdos_ret],ax ; save XFN (IFN for FCB open) to return 0 00008BF5 E8[0000] call timestamp_dhndl 0 00008BF8 26804F0540 or byte [es:DHNDL_ATTR + bx],DHAT_READY 176 ; jmp open_dup_dev 177 178 open_dup_dev: 179 ;------------ 180 ; On Entry: 181 ; ES:BX = DHNDL_ 182 ; On Exit: 183 ; None 184 ; 0 00008BFD B00D mov al,CMD_DEVICE_OPEN 186 ; jmp open_close_dev ; call device open routine 187 188 open_close_dev: 189 ;-------------- 190 ; entry: ES:BX = DHNDL_ 191 ; AL = cmd_type (CMD_DEVICE_OPEN/CMD_DEVICE_CLOSE) 192 ; 0 00008BFF 1E push ds 0 00008C00 06 push es 0 00008C01 53 push bx 0 00008C02 56 push si 0 00008C03 26C57707 lds si,[es:DHNDL_DEVPTR + bx] ; DS:SI -> device driver 0 00008C07 F744040008 test word [DEVHDR.ATTRIB + si],DA_REMOVE 0 00008C0C 7412 jz ocdev1 ; does the device support OPEN/CLOSE/RM 0 00008C0E 83EC09 sub sp,RH13_LEN-2*2 ; make space on stack for RH_ 0 00008C11 50 push ax ; RH_CMD = AL 0 00008C12 B80D00 mov ax,RH13_LEN 0 00008C15 50 push ax ; RH_LEN = RH13_LEN 0 00008C16 16 push ss 0 00008C17 07 pop es 0 00008C18 89E3 mov bx,sp ; ES:BX -> RH_ 0 00008C1A E8[0000] call device_driver ; call the device driver 0 00008C1D 83C40D add sp,RH13_LEN ; recover stack space 209 ocdev1: 0 00008C20 5E pop si 0 00008C21 5B pop bx 0 00008C22 07 pop es 0 00008C23 1F pop ds 0 00008C24 C3 ret 215 216 dup_dev: 217 ;------- 218 ; On Entry: 219 ; ES:BX -> DHNDL_ 220 ; On Exit: 221 ; None 222 ; AX trashed 223 ; 0 00008C25 268B4705 mov ax,[es:DHNDL_WATTR + bx] 0 00008C29 A880 test al,DHAT_DEV 0 00008C2B 7405 jz dup_dev10 ; skip if disk file 0 00008C2D A90080 test ax,DHAT_REMOTE ; or remote 0 00008C30 74CB jz open_dup_dev 229 dup_dev10: 0 00008C32 C3 ret 231 232 233 close_dev: ; close character device handle 234 ;--------- 235 ; entry: FDOS_PB+2 = user file handle 236 ; ES:BX = file handle 237 ; NOTE: This is called with the MXdisk owned 238 0 00008C33 B00E mov al,CMD_DEVICE_CLOSE 0 00008C35 E8C7FF call open_close_dev ; call device close routine 0 00008C38 E8[0000] call release_handle ; release the XFN 0 00008C3B 26FF0F dec word [es:DHNDL_COUNT + bx] ; one less XFN refers to this IFN 0 00008C3E C3 ret 244 245 246 write_dev: ; write to character device handle 247 ;--------- 248 ; entry: ES:BX -> DHNDL_ structure 249 ; 250 0 00008C3F B108 mov cl,CMD_OUTPUT ; OUTPUT driver function 0 00008C41 26804F0540 or byte [es:DHNDL_ATTR + bx],DHAT_READY 0 00008C46 268A4705 mov al,[es:DHNDL_ATTR + bx] ; get file info 0 00008C4A 2427 and al,DHAT_BIN+DHAT_NUL+DHAT_CIN+DHAT_COT 0 00008C4C 3C03 cmp al,DHAT_CIN+DHAT_COT ; is it cooked console? 0 00008C4E 7543 jne inst_io ; no, device driver i/o 0 00008C50 8B7602 mov si,[2 + bp] ; SI -> parameter block 0 00008C53 8B4C08 mov cx,[8 + si] ; CX = string length 0 00008C56 E319 jcxz write_dev20 ; exit if nothing to write 0 00008C58 C47C04 les di,[4 + si] ; ES:DI -> string to print 0 00008C5B B01A mov al,'Z'-40h ; we have to stop at ^Z 0 00008C5D F2AE repne scasb ; scan for ^Z character 0 00008C5F 7504 jne write_dev10 ; skip if ^Z not found 0 00008C61 41 inc cx ; include ^Z in count of chars to skip 0 00008C62 294C08 sub [8 + si],cx ; subtract from total count 266 write_dev10: 0 00008C65 8B5C02 mov bx,[2 + si] ; BX = handle number 0 00008C68 8B4C08 mov cx,[8 + si] ; CX = string length 0 00008C6B 8B7404 mov si,[4 + si] ; ES:SI -> string to print 0 00008C6E E8[0000] call cooked_write ; write w/ tab expansion & ^C checking 271 write_dev20: 0 00008C71 29DB sub bx,bx ; no errors 0 00008C73 C3 ret ; return the result 274 275 276 277 read_dev: ; read to character device handle 278 ;-------- 279 ; entry: ES:BX -> DHNDL_ structure 280 0 00008C74 268A4705 mov al,[es:DHNDL_ATTR + bx] ; get the file info 0 00008C78 88C4 mov ah,al ; save ioctl info 0 00008C7A 2423 and al,DHAT_BIN+DHAT_CIN+DHAT_COT 0 00008C7C 3C03 cmp al,DHAT_CIN+DHAT_COT ; is it cooked console? 0 00008C7E 7503 jne rddev1 ; skip if binary or not console 0 00008C80 E9C600 jmp read_con ; read from console handle 287 ; return the result 288 rddev1: 0 00008C83 F6C440 test ah,DHAT_READY ; previous EOF ? 0 00008C86 7509 jnz rddev2 ; yes we return now 0 00008C88 8B7E02 mov di,[2 + bp] ; DI -> parameter block 0 00008C8B C745080000 mov word ptr [8 + di],0 ; zero bytes xfered 0 00008C90 C3 ret 294 rddev2: 0 00008C91 B104 mov cl,CMD_INPUT 296 inst_io: 297 ; ES:BX = DHNDL_, CL = command 0 00008C93 83EC16 sub sp,RH4_CDEV_LEN ; make RH_ on stack 0 00008C96 89DF mov di,bx ; save address DHNDL_ in DI 0 00008C98 89E3 mov bx,sp ; SS:BX -> request header 301 0 00008C9A 884F02 mov [RH_CMD + bx],cl 0 00008C9D C60716 mov byte [RH_LEN + bx],RH4_CDEV_LEN 0 00008CA0 C747030000 mov word [RH_STATUS + bx],0 ; status OK in case of zero chars 0 00008CA5 8B7602 mov si,[2 + bp] ; DS:SI -> parameter block 0 00008CA8 8D7404 lea si,[4 + si] ; point at buffer offset 0 00008CAB AD lodsw ; get buffer offset 308 ; Normalising the address has been unnecessary so far 309 ; push ax 310 ; and ax,15 ; normalise the address 311 ; pop cx 312 ; shr cx,1 ! shr cx,1 313 ; shr cx,1 ! shr cx,1 0 00008CAC 89470E mov [RH4_BUFOFF + bx],ax ; set buffer offset in request header 0 00008CAF AD lodsw ; get buffer segment 316 ; add ax,cx ; add in normalised offset/16 0 00008CB0 894710 mov [RH4_BUFSEG + bx],ax ; get buffer segment in request header 0 00008CB3 AD lodsw ; get byte count 0 00008CB4 91 xchg ax,cx ; byte count in CX 320 321 ; Parameter block created on stack at SS:BX and initialised for xfer 322 ; ES:DI -> DHNDL_, CX = total number of bytes to xfer 323 324 inst_io20: 0 00008CB5 894F12 mov [RH4_COUNT + bx],cx ; try and do this many 0 00008CB8 26F6450524 test byte [es:DHNDL_ATTR + di],DHAT_BIN+DHAT_NUL 327 ; are we in binary mode ? 0 00008CBD E369 jcxz inst_io30 ; return on zero length xfer 0 00008CBF 7515 jnz inst_io25 ; binary, skip calling PCMODE 0 00008CC1 C747120100 mov word [RH4_COUNT + bx],1 ; do one char at a time 0 00008CC6 E8[0000] call break_check ; call the break check routine 0 00008CC9 807F0208 cmp byte [RH_CMD + bx],CMD_OUTPUT ; which way are we going 0 00008CCD 7507 jne inst_io25 0 00008CCF E87000 call inst_io_getchar ; AL = 1st char in the buffer 0 00008CD2 3C1A cmp al,1Ah ; EOF - don't send it or anything after 0 00008CD4 7452 je inst_io30 ; and exit without xfering any 337 inst_io25: 0 00008CD6 1E push ds 0 00008CD7 06 push es 0 00008CD8 57 push di 0 00008CD9 51 push cx 0 00008CDA 26C57507 lds si,[es:DHNDL_DEVPTR + di] ; DS:SI -> device driver 0 00008CDE 16 push ss 0 00008CDF 07 pop es ; ES:BX -> RH_ 0 00008CE0 E8[0000] call device_driver ; execute the command 0 00008CE3 59 pop cx 0 00008CE4 5F pop di 0 00008CE5 07 pop es 0 00008CE6 1F pop ds 0 00008CE7 7916 jns inst_io_continue ; if no errors carry on 0 00008CE9 06 push es 0 00008CEA 26C47507 les si,[es:DHNDL_DEVPTR + di] ; ES:SI -> device driver 0 00008CEE E8[0000] call char_error ; this will handle the Int 24 0 00008CF1 07 pop es 0 00008CF2 3C01 cmp al,ERR_RETRY ; what should we do ? 0 00008CF4 74BF je inst_io20 ; retry the operation 0 00008CF6 7730 ja inst_io30 ; fail - return error 0 00008CF8 C747030001 mov word [RH_STATUS + bx],RHS_DONE 0 00008CFD EB07 jmp inst_io_ignore ; ignore - fiddle status and 360 inst_io_continue: ; say we did it all 0 00008CFF 8B5712 mov dx,[RH4_COUNT + bx] ; how many did we xfer ? 0 00008D02 85D2 test dx,dx ; if we haven't done any 0 00008D04 7422 jz inst_io30 ; we are stuck so exit now 364 inst_io_ignore: 0 00008D06 E83900 call inst_io_getchar ; AL = 1st char in the buffer 0 00008D09 01570E add [RH4_BUFOFF + bx],dx ; it may not enough so adjust offset 0 00008D0C 29D1 sub cx,dx ; and number still to do 0 00008D0E 807F0204 cmp byte [RH_CMD + bx],CMD_INPUT ; which way are we going - if input 0 00008D12 75A1 jne inst_io20 ; we need to check for CR/EOF 0 00008D14 26F6450524 test byte [es:DHNDL_ATTR + di],DHAT_BIN+DHAT_NUL 0 00008D19 750D jnz inst_io30 ; if BIN then exit now 0 00008D1B 3C0D cmp al,13 ; is it a CR character ? 0 00008D1D 7409 je inst_io30 ; yes, we stop now 0 00008D1F 3C1A cmp al,1Ah ; is it the EOF character ? 0 00008D21 7592 jne inst_io20 ; yes, we aren't ready 0 00008D23 26806505BF and byte [es:DHNDL_ATTR + di],~ DHAT_READY 377 inst_io30: 0 00008D28 8B7E02 mov di,[2 + bp] ; DI -> parameter block 0 00008D2B 294D08 sub [8 + di],cx ; subtract # not xfered from byte count 380 0 00008D2E 8B4703 mov ax,[RH_STATUS + bx] ; get result for later 0 00008D31 29DB sub bx,bx ; assume no errors 0 00008D33 85C0 test ax,ax ; test error bit (8000h) 0 00008D35 7907 jns rddev_no_err ; skip if ERROR set 0 00008D37 88C3 mov bl,al ; AL is error code 0 00008D39 F7DB neg bx ; make it negative code 0 00008D3B 83C3ED add bx,ED_PROTECT ; normalize for extended errors 388 rddev_no_err: 0 00008D3E 83C416 add sp,RH4_CDEV_LEN ; free up RH_ on stack 0 00008D41 C3 ret ; return BX 391 392 inst_io_getchar: 0 00008D42 1E push ds 0 00008D43 C5770E lds si,[RH4_BUFFER + bx] ; point to the users buffer 0 00008D46 AC lodsb ; get 1st char in the buffer 0 00008D47 1F pop ds 0 00008D48 C3 ret 398 399 400 read_con: ; handle read from cooked console 401 ;-------- 402 ; entry: AH = DHNDL_ATTR 403 ; ES:BX -> DHNDL_ 404 ; 2[BP] -> F_DOS parameter block 405 ; exit: BX = return value 406 0 00008D49 31C9 xor cx,cx ; assume we've already had EOF 0 00008D4B F6C440 test ah,DHAT_READY ; now see if we have 0 00008D4E 7502 jnz con_dev_not_eof 0 00008D50 EB7B jmp con_dev_exit ; yes, just return zero chars read 411 con_dev_not_eof: 0 00008D52 06 push es 0 00008D53 53 push bx ; save DHNDL_ 414 con_dev_loop: 0 00008D54 8B1E[0000] mov bx,word ptr [fdos_buf] ; get # of bytes already used 0 00008D58 31C0 xor ax,ax 0 00008D5A 86C7 xchg al,bh ; get # bytes in the buffer 0 00008D5C 40 inc ax 0 00008D5D 40 inc ax ; also count the CR/LF 0 00008D5E 29D8 sub ax,bx ; have we any bytes left in the buffer? 0 00008D60 7736 ja con_dev_cont ; yes, return them 422 ; no, we need a fresh input line 423 ; mov fdos_buf,128 ; read up to 128 characters 0 00008D62 C606[0000]80 mov byte [fdos_buf],CMDLINE_LEN ; read up to 128 characters 0 00008D67 8B7602 mov si,[2 + bp] ; SI -> parameter block 0 00008D6A 8B5C02 mov bx,[2 + si] ; BX = input handle 0 00008D6D 1E push ds 0 00008D6E 07 pop es 0 00008D6F BA[0000] mov dx,offset fdos_buf ; ES:DX -> console buffer 0 00008D72 89D9 mov cx,bx ; output to same handle as input 0 00008D74 53 push bx 0 00008D75 55 push bp 0 00008D76 E8[0000] call read_line ; read edited line 0 00008D79 5D pop bp 0 00008D7A 8A1E[0100] mov bl,[fdos_buf+1] ; # byte we have read 0 00008D7E B700 mov bh,0 ; BX = # of characters read 0 00008D80 C787[0200]0D0A mov word ptr [fdos_buf+2 + bx],0A0Dh; append carriage return/line feed 0 00008D86 C606[0000]00 mov byte [fdos_buf],0 ; start reading at beginning 0 00008D8B 8DB7[0300] lea si,[fdos_buf+3 + bx] ; Echo the LF character to the 0 00008D8F 5B pop bx ; Same Output handle 0 00008D90 B90100 mov cx,1 ; Only One Character 0 00008D93 E8[0000] call cooked_write 0 00008D96 EBBC jmp con_dev_loop 444 445 con_dev_cont: ; BX = buffer offset 0 00008D98 8B7E02 mov di,[2 + bp] ; DI -> parameter block 0 00008D9B 8B4D08 mov cx,[8 + di] ; CX = # of bytes to read 0 00008D9E 39C1 cmp cx,ax ; reading more than available? 0 00008DA0 7602 jbe con_dev_ok ; no, read as much as you want 0 00008DA2 89C1 mov cx,ax ; else take all that there is 451 con_dev_ok: 0 00008DA4 000E[0000] add [fdos_buf],cl ; update buffer index for next time 0 00008DA8 C47D04 les di,[4 + di] ; ES:DI -> buffer to read into 0 00008DAB 8DB7[0200] lea si,[fdos_buf+2 + bx] ; DS:SI -> function 10 buffer 0 00008DAF 51 push cx ; save count 0 00008DB0 F3A4 rep movsb ; read all the data 0 00008DB2 59 pop cx ; restore count 0 00008DB3 B01A mov al,1Ah ; now we look for EOF mark... 0 00008DB5 1E push ds 0 00008DB6 07 pop es 0 00008DB7 8DBF[0200] lea di,[fdos_buf+2 + bx] ; ES:DI -> function 10 buffer 0 00008DBB 89CE mov si,cx ; keep count safe 0 00008DBD F2AE repne scasb 0 00008DBF 87CE xchg cx,si ; restore count 0 00008DC1 5B pop bx ; recover DHNDL_ 0 00008DC2 07 pop es 0 00008DC3 7508 jne con_dev_exit ; if no EOF, skip to exit 0 00008DC5 29F1 sub cx,si ; subtract any after EOF mark 0 00008DC7 49 dec cx ; and the EOF mark itself 0 00008DC8 26806705BF and byte [es:DHNDL_ATTR + bx],~ DHAT_READY 471 con_dev_exit: 0 00008DCD 8B7E02 mov di,[2 + bp] ; DI -> parameter block 0 00008DD0 894D08 mov [8 + di],cx ; set # of characters read 0 00008DD3 29DB sub bx,bx ; good return code 0 00008DD5 C3 ret 476 477 478 479 first_dev: ; F_DOS FIRST call on device performed 480 ;--------- ; Called with MXDisk 481 ; On Entry: 482 ; ES:BX -> device header 483 ; On Exit: 484 ; dma_buffer initialised with device name 485 ; 0 00008DD6 8CC2 mov dx,es ; DX:BX -> device header 0 00008DD8 E8[0000] call les_di_dmaptr ; ES:DI -> DMA buffer 0 00008DDB B0FF mov al,0FFh ; invalidate search state for NEXT 0 00008DDD B91500 mov cx,21 0 00008DE0 F3AA rep stosb 0 00008DE2 B040 mov al,40h ; mark it as a device 0 00008DE4 AA stosb 0 00008DE5 29C0 sub ax,ax 0 00008DE7 B90400 mov cx,4 0 00008DEA F3AB rep stosw ; zero time, date, file size 496 0 00008DEC 8D770A lea si,[10 + bx] 0 00008DEF 1E push ds 0 00008DF0 8EDA mov ds,dx ; DS:SI -> name in device header 0 00008DF2 B90400 mov cx,4 0 00008DF5 F3A5 rep movsw ; copy device name across 0 00008DF7 1F pop ds 503 0 00008DF8 B90800 mov cx,8 505 frstdev1: ; scan off trailing spaces 0 00008DFB 26807DFF20 cmp byte ptr [es:di-1],' ' 0 00008E00 7503 jne frstdev2 0 00008E02 4F dec di 0 00008E03 E2F6 loop frstdev1 510 frstdev2: 0 00008E05 B000 mov al,0 0 00008E07 AA stosb ; add a trailing NUL 0 00008E08 C3 ret 514 515 516 ioc6_dev: ; IOCTL(6) - input status for device 517 ;-------- 518 ; entry: ES:BX -> DHNDL_ 519 0 00008E09 B005 mov al,CMD_INPUT_NOWAIT 0 00008E0B EB02 jmp ioc67d ; call the device driver 522 523 524 ioc7_dev: ; IOCTL(7) - output status for device 525 ;-------- 526 ; entry: ES:BX -> DHNDL_ 527 0 00008E0D B00A mov al,CMD_OUTPUT_STATUS ; OUTPUT STATUS 529 ioc67d: ; common code for I/O STATUS 0 00008E0F 1E push ds 0 00008E10 83EC0A sub sp,RH5_LEN-2*2 ; allocate request header on stack 0 00008E13 50 push ax ; RH_CMD = AL 0 00008E14 B80E00 mov ax,RH5_LEN 0 00008E17 50 push ax ; RH_LEN = RH5_LEN 0 00008E18 26C57707 lds si,[es:DHNDL_DEVPTR + bx] ; DS:SI -> device driver 0 00008E1C 16 push ss 0 00008E1D 07 pop es 0 00008E1E 89E3 mov bx,sp ; ES:BX -> RH_ 0 00008E20 26C6470D00 mov byte [es:RH5_CHAR + bx],0 ; zero the char 0 00008E25 E8[0000] call device_driver ; do the CALLF's to the device driver 0 00008E28 30D2 xor dl,dl ; assume not ready 0 00008E2A 268A770D mov dh,[es:RH5_CHAR + bx] ; possible peeked character 0 00008E2E 83C40E add sp,RH5_LEN ; recover stack space 0 00008E31 1F pop ds 0 00008E32 A90082 test ax,RHS_ERROR+RHS_BUSY ; test if BUSY bit set in status 0 00008E35 7502 jnz ioc67d_ret ; device not ready if error or busy 0 00008E37 FECA dec dl ; return ready DL = FF 548 ioc67d_ret: 0 00008E39 8B7602 mov si,[2 + bp] ; SI -> user's parameter block 0 00008E3C 895406 mov [6 + si],dx ; update returned status 0 00008E3F 29DB sub bx,bx ; no error occurred 0 00008E41 C3 ret ; for now 553 554 BDOS_CODE ends 555 556 end ; of CDEVIO.A86 === Trace listing source: drdos/bin/fioctl.lst 1 ;title 'FDOS IOCTL - DOS file system input/output control' 2 ; File : $FIOCTL.ASM$ 3 ; 4 ; Description : 5 ; 6 ; Original Author : DIGITAL RESEARCH 7 ; 8 ; Last Edited By : $CALDERA$ 9 ; 10 ;-----------------------------------------------------------------------; 11 ; Copyright Work of Caldera, Inc. All Rights Reserved. 12 ; 13 ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, 14 ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. 15 ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES 16 ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF 17 ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO 18 ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE 19 ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE 20 ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, 21 ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, 22 ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, 23 ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF 24 ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT 25 ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND 26 ; CIVIL LIABILITY. 27 ;-----------------------------------------------------------------------; 28 ; 29 ; *** Current Edit History *** 30 ; *** End of Current Edit History *** 31 ; $Log$ 32 ; FIOCTL.A86 1.18 93/12/09 23:39:17 33 ; Move non-inherited bit to correct place in file handle 34 ; FIOCTL.A86 1.17 93/11/03 13:38:29 35 ; Int 21 4409 return 0x0080 if drive is joined 36 ; FIOCTL.A86 1.16 93/11/02 18:04:17 37 ; Int21/4400 from file returns AH=0 38 ; FIOCTL.A86 1.15 93/09/14 20:03:15 39 ; Trust LFLG_PHYSICAL 40 ; FIOCTL.A86 1.12 93/06/17 22:11:50 41 ; support for ioctl 10/11 query ioctl support 42 ; FIOCTL.A86 1.11 93/06/16 16:21:37 43 ; Codepage preparation bug fixed 44 ; ENDLOG 45 46 ; Date Modification 47 ; --------- --------------------------------------- 48 ; 29 Jun 89 Initial version splits from FDOS 49 ; 21 Nov 89 iocE/F use relative unit number 50 ; 12 Dec 89 ioc2/3 zero the unused portions of req hdr 51 ; save a few bytes in other ioc's while I'm here 52 ; 4 Jun 90 default file access permissions and user group support 53 ; 5 Jun 90 ioc0/1 tidied up 54 ; 12 Jun 90 get_doshndl parameter in BX not AX 55 ; 2 Oct 90 net_vec moves to per-VC basis (info held in CCB_) 56 ; 13 feb 91 ioc1 tests FHIO_DEV, not HM_DEV, (123 MSNet printing) 57 ; 7 may 91 ioc2,ioc3,ioc6,ioc7,iocC destabilised for Lanstatic 58 ; by-product is ioc6 for disks returns read-ahead char 59 ; in AH 60 ; 28 feb 92 ioctl C checks bit 6 not bit 14 in DEVHDR.ATTRIB 61 ; 3 aug 92 ioctl C/D pass thru' SI/DI 62 ; 5 aug 92 substatial ioctl rework saves a few bytes - ioctl 63 ; request header now built by PCMODE 64 65 group PCMCODE BDOS_CODE 66 group PCMDATA BDOS_DATA PCMODE_DATA 67 68 ASSUME DS:PCMDATA 69 70 [list -] 79 === Switch to base=00C180h -> "PCMODE_DATA" 80 section PCMODE_DATA public align=1 class=DATA 81 extrn ioctlRH:byte ; request header is build in PCMODE 82 ; data area 83 PCMODE_DATA ends 84 === Switch to base=00C180h -> "BDOS_DATA" 85 section BDOS_DATA public align=2 class=DATA 86 extrn fdos_pb:word 87 extrn fdos_ret:word 88 extrn last_drv:byte 89 extrn req_hdr:byte 90 %ifdef PASSWORD 91 extrn global_password:word 92 %endif 93 BDOS_DATA ends 94 === Switch to base=000000h -> "BDOS_CODE" 95 section BDOS_CODE public align=1 class=CODE 96 97 extrn local_disk:near 98 extrn device_driver:near 99 extrn block_device_driver:near 100 extrn fdos_error:near 101 extrn fdos_ED_DRIVE:near 102 extrn fdos_ED_FUNCTION:near 103 extrn fdos_read:near 104 extrn get_ddsc:near 105 extrn vfy_dhndl_ptr:near 106 extrn get_pb2_drive:near 107 extrn ioc6_dev:near ; IOCTL(6): input status for device 108 extrn ioc7_dev:near ; IOCTL(7): output status for device 109 extrn vfy_dhndl_ptr:near 110 extrn verify_handle:near 111 extrn reload_registers:near 112 %ifdef JOIN 113 extrn get_ldt:near 114 %endif 115 %ifdef PASSWORD 116 extrn hash_pwd:near 117 %endif 118 119 public fdos_ioctl 120 121 ; INPUT/OUTPUT CONTROL (IOCTL) 122 123 ; +----+----+----+----+----+----+----+----+----+----+ 124 ; | 26 | param | func | request header | 125 ; +----+----+----+----+----+----+----+----+----+----+ 126 127 128 ; entry: 129 ; ------ 130 ; param: handle/drive on some functions 131 ; func: sub function (0-A) 132 ; request header: far pointer to IOCTL request header 133 134 ; exit: 135 ; ----- 136 ; AX: return code or error code ( < 0) 137 ; param: return value from some functions 138 139 140 0 00008E42 [3A00] ioctl_tbl dw ioctl0 ; 0-get handle status 0 00008E44 [5D00] dw ioctl1 ; 1-set handle status 0 00008E46 [7700] dw ioctl2 ; 2-receive control string (handle) 0 00008E48 [7700] dw ioctl3 ; 3-send control string (handle) 0 00008E4A [8A00] dw ioctl4 ; 4-receive control string (drive) 0 00008E4C [8A00] dw ioctl5 ; 5-send control string (drive) 0 00008E4E [2001] dw ioctl6 ; 6-input status 0 00008E50 [9801] dw ioctl7 ; 7-output status 0 00008E52 [F300] dw ioctl8 ; 8-removable media check 0 00008E54 [B101] dw ioctl9 ; 9-networked drive check 0 00008E56 [F501] dw ioctlA ; A-networked handle check 152 %ifdef PASSWORD 0 00008E58 [3802] dw ioctl54 ; B-set global password 154 %else 155 dw device_ED_FUNCTION 156 %endif 0 00008E5A [7700] dw ioctlC ; C-code page support 0 00008E5C [8A00] dw ioctlD ; D-generic IOCTL disk i/o 0 00008E5E [FF01] dw ioctlE ; E-get logical drive 0 00008E60 [0602] dw ioctlF ; F-set logical drive 0 00008E62 [7700] dw ioctl10 ; 10-query IOCTL for char devs 0 00008E64 [8A00] dw ioctl11 ; 11-query IOCTL for disks 163 164 NUM_IOCTL equ (offset $ - offset ioctl_tbl)/2 165 166 167 168 fdos_ioctl: 169 ;---------- 0 00008E66 8B5E02 mov bx,[2 + bp] ; BX -> parameter block 0 00008E69 8B5F04 mov bx,[4 + bx] ; get I/O control subfunction 0 00008E6C 83FB12 cmp bx,NUM_IOCTL ; is it in the supported range? 0 00008E6F 7307 jae device_ED_FUNCTION ; skip if value too large 0 00008E71 D1E3 shl bx,1 ; else make it word index 0 00008E73 2EFFA7[0000] jmp [cs:ioctl_tbl + bx] ; call the right function 176 device_ED_FUNCTION: 0 00008E78 BBFFFF mov bx,ED_FUNCTION ; "invalid function" 0 00008E7B C3 ret 179 180 181 182 ioctl0: ; get device status 183 ;------ 184 ; Note: We store the binary flag for the standard console 185 ; handles in the console mode, not in the file handle, 186 ; as the handles are shared across all consoles... 187 0 00008E7C E8[0000] call vfy_dhndl_ptr ; check if good handle 0 00008E7F 268B4705 mov ax,[es:DHNDL_WATTR + bx] ; get attrib from doshndl 0 00008E83 F6C480 test ah,DHAT_REMOTE/256 0 00008E86 B400 mov ah,0 ; files/networks return 0 in AH/DH 0 00008E88 750C jnz device_OK ; return attrib if network device 0 00008E8A A880 test al,DHAT_DEV ; or a file 0 00008E8C 7408 jz device_OK 0 00008E8E 26C45F07 les bx,[es:DHNDL_DEVPTR + bx] ; get real device driver address 0 00008E92 268A6705 mov ah,byte ptr [es:5 + bx] ; get device driver attribute 197 ; jmp device_OK 198 199 device_OK: 200 ;--------- 0 00008E96 8B5E02 mov bx,[2 + bp] ; get parameter block address 0 00008E99 894706 mov [6 + bx],ax ; save returned status 0 00008E9C 31DB xor bx,bx ; successful return code 0 00008E9E C3 ret 205 206 ioctl1: ; set device status 207 ;------ 0 00008E9F E8[0000] call vfy_dhndl_ptr ; make sure this is an open handle 0 00008EA2 26F747058000 test word [es:DHNDL_WATTR + bx],DHAT_DEV 0 00008EA8 74CE jz device_ED_FUNCTION ; can't set status of disk files 0 00008EAA A1[0E00] mov ax,word ptr [ioctlRH+14] 212 ; pick up new device status 0 00008EAD 84E4 test ah,ah ; test if high byte is zero 0 00008EAF 75C7 jnz device_ED_FUNCTION ; skip if O.K. 0 00008EB1 0C80 or al,DHAT_DEV ; make sure it stays a device 0 00008EB3 26884705 mov [es:DHNDL_ATTR + bx],al ; store ioctl state in doshndl 0 00008EB7 EBDD jmp device_OK ; success 218 219 220 ioctl2: ; receive control string (devicehandle) 221 ;------ 222 ioctl3: ; send control string (device handle) 223 ;------ 224 ioctlC: ; generic ioctl (device handle) 225 ;------ 226 ioctl10: ; query ioctl support (device handle) 227 ;------- 0 00008EB9 E8[0000] call vfy_dhndl_ptr ; check file handle # 0 00008EBC E8[0000] call local_disk ; get MXdisk 0 00008EBF E8[0000] call verify_handle ; make sure the handle is good 0 00008EC2 736E jnc short_fdos_ED_FUNCTION ; and is for a DEVICE 0 00008EC4 31C9 xor cx,cx ; device relative unit # always zero 0 00008EC6 26C47707 les si,[es:DHNDL_DEVPTR + bx] ; ES:SI -> device driver 0 00008ECA EB0E jmp ioc2345CDcommon ; now use common code 235 236 ioctl4: ; receive control string (drive) 237 ;------ 238 ioctl5: ; send control string (drive) 239 ;------ 240 ioctlD: ; generic ioctl (drive) 241 ;------ 242 ioctl11: ; query ioctl support (drive) 243 ;------- 0 00008ECC E8[0000] call local_disk ; get MXdisk, switch stack 0 00008ECF E83000 call get_pb2_ddsc ; get drives DDSC_ 0 00008ED2 268A4F01 mov cl,[es:DDSC_RUNIT + bx] ; get relative unit # 0 00008ED6 26C47713 les si,[es:DDSC_DEVHEAD + bx] ; ES:SI -> device header 248 ; jmp ioctl2345Common ; now use common code 249 250 ioc2345CDcommon: 251 ;--------------- 252 ; On Entry: 253 ; ES:SI -> device driver header 254 ; CL = media byte (0 if character device) 255 ; CH = relative unit (0 if character device) 256 ; MXDisk obtained 257 ; On Exit: 258 ; IOCTL performed 259 ; 0 00008EDA A1[0600] mov ax,[fdos_pb+6] ; device driver support required 261 DEVHDR.ATTRIB equ ATTRIB ; NASM port label 0 00008EDD 26854404 test [es:DEVHDR.ATTRIB + si],ax ; does device driver support function ? 0 00008EE1 744F jz short_fdos_ED_FUNCTION 0 00008EE3 1E push ds 0 00008EE4 06 push es 0 00008EE5 1F pop ds ; DS:SI -> device driver 0 00008EE6 16 push ss 0 00008EE7 07 pop es 0 00008EE8 BB[0000] mov bx,offset ioctlRH ; ES:BX -> request header 0 00008EEB 26884F01 mov [es:RH_UNIT + bx],cl ; set relative unit for block devices 0 00008EEF E8[0000] call device_driver ; call the device driver 0 00008EF2 1F pop ds ; check for errors on return 273 ; jmp fdos_error_check 274 275 fdos_error_check: 276 ;------------- 277 ; On Entry: 278 ; AX = Req Status 279 ; On Exit: 280 ; SIGN set if an error, AX&BX = Internal DOS error code 281 ; 0 00008EF3 85C0 test ax,ax ; top bit == 1 if error 0 00008EF5 790A jns fdos_ioc_ec10 ; skip if no errors 0 00008EF7 30E4 xor ah,ah 0 00008EF9 83C013 add ax,-ED_PROTECT 0 00008EFC F7D8 neg ax 0 00008EFE E9[0000] jmp fdos_error ; return critical error 288 fdos_ioc_ec10: 0 00008F01 C3 ret 290 291 ; IOCTL subfunctions: 292 293 294 get_pb2_ddsc: 295 ;------------ 296 ; On Entry: 297 ; local_disk called, pick us drive from pb2 298 ; On Exit: 299 ; ES:BX -> DDSC_ for the drive 300 ; 0 00008F02 E8[0000] call get_pb2_drive ; get specified drive 0 00008F05 3A06[0000] cmp al,[last_drv] ; is it a valid drive 0 00008F09 7724 ja bad_drive 0 00008F0B E8[0000] call get_ldt ; ES:BX -> LDT for this drive 0 00008F0E 7219 jc get_pb2_ddsc10 ; no LDT, physical=logical 0 00008F10 268B4743 mov ax,[es:LDT_FLAGS + bx] 0 00008F14 F6C480 test ah,LFLG_NETWRKD/256 0 00008F17 7519 jnz short_fdos_ED_FUNCTION ; reject network drives 0 00008F19 F6C440 test ah,LFLG_PHYSICAL/256 0 00008F1C 7411 jz bad_drive 0 00008F1E F6C420 test ah,LFLG_JOINED/256 0 00008F21 750C jnz bad_drive ; reject JOIN'd drives 0 00008F23 268A07 mov al,[es:LDT_NAME + bx] ; get physical drive from LDT 0 00008F26 241F and al,1Fh ; convert to 1 based drive 0 00008F28 48 dec ax ; make that zero based 316 get_pb2_ddsc10: 0 00008F29 E8[0000] call get_ddsc ; ES:BX -> DDSC_ 0 00008F2C 7201 jc bad_drive ; or does it? 0 00008F2E C3 ret 320 321 bad_drive: 0 00008F2F E9[0000] jmp fdos_ED_DRIVE ; invalid drive specified 323 324 short_fdos_ED_FUNCTION: 0 00008F32 E9[0000] jmp fdos_ED_FUNCTION 326 327 328 ioctl8: ; removable media check 329 ;------ 0 00008F35 E8[0000] call local_disk ; get MXdisk, switch stack 0 00008F38 E8C7FF call get_pb2_ddsc ; get drives DDSC_ 0 00008F3B 1E push ds 0 00008F3C 26C57713 lds si,[es:DDSC_DEVHEAD + bx] ; DS:SI -> device driver 0 00008F40 F744040008 test word [DEVHDR.ATTRIB + si],DA_REMOVE 0 00008F45 1F pop ds ; do we support the check ? 0 00008F46 74EA jz short_fdos_ED_FUNCTION ; if we don't then don't ask 0 00008F48 C606[0000]0D mov byte [req_hdr],RH15_LEN 0 00008F4D C606[0200]0F mov byte [req_hdr+2],CMD_FIXED_MEDIA 0 00008F52 E8[0000] call block_device_driver ; call the device driver 0 00008F55 78DB js short_fdos_ED_FUNCTION 0 00008F57 250002 and ax,RHS_BUSY ; BUSY bit set if permanent - we just 0 00008F5A 86E0 xchg ah,al ; need to get bit in the right place 0 00008F5C D1E8 shr ax,1 ; now 1 if permanent media 0 00008F5E A3[0600] mov [fdos_pb+6],ax ; return status removable (=0) 345 ioctl8_10: 0 00008F61 C3 ret 347 348 349 350 ioctl6: ; file input status 351 ;------ 0 00008F62 E8[0000] call vfy_dhndl_ptr ; make sure this is an open handle 0 00008F65 268B4705 mov ax,[es:DHNDL_WATTR + bx] 0 00008F69 A90080 test ax,DHAT_REMOTE 0 00008F6C 7508 jnz ioctl6_10 ; always ask networked handles 0 00008F6E A98000 test ax,DHAT_DEV 0 00008F71 7403 jz ioctl6_10 ; files are always askable 0 00008F73 E9[0000] jmp ioc6_dev 359 360 ioctl6_10: ; disk files/network devices 0 00008F76 26FF7715 push word [es:DHNDL_POSLO + bx] ; save current position in file 0 00008F7A 26FF7717 push word [es:DHNDL_POSHI + bx] ; so we can read ahead 0 00008F7E 26FF7747 push word [es:DHNDL_POSXLO + bx] 0 00008F82 26FF7749 push word [es:DHNDL_POSXHI + bx] 0 00008F86 06 push es 0 00008F87 53 push bx ; save DHNDL_ too.. 0 00008F88 55 push bp ; save stack frame 0 00008F89 8B7602 mov si,[2 + bp] ; SI -> parameter block 0 00008F8C B80100 mov ax,1 0 00008F8F 50 push ax ; read 1 byte ahead 0 00008F90 1E push ds ; use fdos_pb as read-ahead 0 00008F91 8D4406 lea ax,[6 + si] ; buffer 0 00008F94 50 push ax 0 00008F95 FF7402 push word ptr [2 + si] ; user file number 0 00008F98 B83F00 mov ax,MS_X_READ ; READ function #, so we create 0 00008F9B 50 push ax ; a dummy fdos_pb 0 00008F9C 89E3 mov bx,sp ; SS:BX -> dummy fdos_pb 0 00008F9E B9[6B01] mov cx,offset ioctl6_20 ; CX -> return address 0 00008FA1 51 push cx ; Return to here 0 00008FA2 16 push ss ; save parameter segment 0 00008FA3 53 push bx ; save parameter offset 0 00008FA4 50 push ax ; save sub-function 0 00008FA5 89E5 mov bp,sp ; SS:BP -> working variables 0 00008FA7 E8[0000] call fdos_read ; make FDOS_READ do the hard word 0 00008FAA 83C408 add sp,4*2 ; discard param's on stack 386 ioctl6_20: 0 00008FAD 83C408 add sp,4*2 ; discard most of dummy fdos_pb 0 00008FB0 59 pop cx ; return # read 0 00008FB1 83FBA6 cmp bx,ED_LASTERROR ; did we succeed ? 0 00008FB4 7202 jb ioctl6_30 ; if so we can trust # read 0 00008FB6 31C9 xor cx,cx ; else in error assume nothing 392 ioctl6_30: 0 00008FB8 5D pop bp ; recover stack frame 0 00008FB9 5B pop bx ; rewind DHNDL_POS to where 0 00008FBA 07 pop es 0 00008FBB 268F4749 pop word [es:DHNDL_POSXHI + bx] ; it was before we started 0 00008FBF 268F4747 pop word [es:DHNDL_POSXLO + bx] 0 00008FC3 268F4717 pop word [es:DHNDL_POSHI + bx] 0 00008FC7 268F4715 pop word [es:DHNDL_POSLO + bx] 0 00008FCB B8001A mov ax,1a00h ; assume not ready 0 00008FCE E307 jcxz ioctl6_40 0 00008FD0 48 dec ax ; AL = FF, ie. ready 0 00008FD1 8B7602 mov si,[2 + bp] ; SI -> parameter block 0 00008FD4 8A6406 mov ah,byte ptr [6 + si] ; get character we read 405 ioctl6_40: 0 00008FD7 E9BCFE jmp device_OK 407 408 409 ioctl7: ; file output status 410 ;------ 0 00008FDA E8[0000] call vfy_dhndl_ptr ; make sure this is an open handle 0 00008FDD B8FF00 mov ax,0FFh ; assume it's networked/disk 0 00008FE0 268B5705 mov dx,[es:DHNDL_WATTR + bx] 0 00008FE4 F7C20080 test dx,DHAT_REMOTE 0 00008FE8 75ED jnz ioctl6_40 ; networked handles are always ready 0 00008FEA F7C28000 test dx,DHAT_DEV 0 00008FEE 74E7 jz ioctl6_40 ; files are always ready 0 00008FF0 E9[0000] jmp ioc7_dev ; devices we ask... 419 420 421 422 ioctl9: ; networked drive check 423 ;------ 0 00008FF3 E8[0000] call local_disk ; get disk semaphore 0 00008FF6 E8[0000] call get_pb2_drive ; get specified drive 0 00008FF9 E8[0000] call get_ldt ; ES:BX -> LDT for this drive 0 00008FFC 7236 jc ioctl940 0 00008FFE 268B4743 mov ax,[es:LDT_FLAGS + bx] 0 00009002 F6C480 test ah,LFLG_NETWRKD/256 0 00009005 7405 jz ioctl910 431 %if 1 0 00009007 B80010 mov ax,1000h ; return drive as remote 433 %else 434 les di,[es:LDT_PDT + bx] ; pick up network internal pointer 435 mov ax,[es:4 + di] ; pick up garbage 436 or ah,10h ; return drive as remote 437 %endif 0 0000900A EB24 jmp ioctl930 439 440 ioctl910: 0 0000900C F6C440 test ah,LFLG_PHYSICAL/256 0 0000900F 7423 jz ioctl940 0 00009011 F6C410 test ah,LFLG_SUBST/256 0 00009014 92 xchg ax,dx ; save flags 0 00009015 B80080 mov ax,8000h ; assume it's SUBST'd 0 00009018 7509 jnz ioctl920 0 0000901A F6C620 test dh,LFLG_JOINED/256 0 0000901D 86C4 xchg al,ah ; assume it's JOIN'd 0 0000901F 750F jnz ioctl930 0 00009021 31C0 xor ax,ax ; clear if not 451 ioctl920: 0 00009023 50 push ax 0 00009024 E8DBFE call get_pb2_ddsc ; get drives DDSC_ 0 00009027 58 pop ax 0 00009028 26C47713 les si,[es:DDSC_DEVHEAD + bx] ; ES:SI -> device driver 0 0000902C 260B4404 or ax,[es:4 + si] ; get device attributes 457 ioctl930: 0 00009030 A3[0600] mov [fdos_pb+6],ax ; return updated status 0 00009033 C3 ret 460 461 ioctl940: 0 00009034 E9[0000] jmp fdos_ED_DRIVE ; return ED_DRIVE error 463 464 465 ioctlA: ; networked handle check 466 ;------ 0 00009037 E8[0000] call vfy_dhndl_ptr 0 0000903A 268B4705 mov ax,[es:DHNDL_WATTR + bx] 0 0000903E E955FE jmp device_OK ; return attributes 470 471 472 ioctlE: 473 ;------ 0 00009041 E8[0000] call local_disk 0 00009044 B017 mov al,CMD_GET_DEVICE ; get logical device 0 00009046 EB05 jmp iocEFcommon ; common code for IOCTL(E)/IOCTL(F) 477 478 ioctlF: 479 ;------ 0 00009048 E8[0000] call local_disk 0 0000904B B018 mov al,CMD_SET_DEVICE ; set logical device 482 iocEFcommon: 0 0000904D C606[0000]15 mov byte [req_hdr],RH24_LEN 0 00009052 A2[0200] mov [req_hdr+2],al 0 00009055 E8AAFE call get_pb2_ddsc ; get drives DDSC_ 0 00009058 40 inc ax ; make drive one-relative 0 00009059 A2[0D00] mov [req_hdr+13],al ; set this as new drive 0 0000905C 31C0 xor ax,ax ; assume not supported 0 0000905E 1E push ds 0 0000905F 26C57713 lds si,[es:DDSC_DEVHEAD + bx] ; does device driver support function ? 0 00009063 F744044000 test word [DEVHDR.ATTRIB + si],DA_GETSET 0 00009068 1F pop ds 0 00009069 7409 jz iocF_single ; skip if not supported 0 0000906B E8[0000] call block_device_driver ; call the device driver 0 0000906E E882FE call fdos_error_check ; return any errors 0 00009071 A0[0100] mov al,[req_hdr+1] ; get returned drive 497 iocF_single: ; AX = return value 0 00009074 B407 mov ah,7 0 00009076 A3[0600] mov [fdos_pb+6],ax ; return the drive 0 00009079 C3 ret 501 502 %ifdef PASSWORD 503 504 ioctl54: ; set global password 505 ;------- 0 0000907A E8[0000] call local_disk ; get the MX disk 0 0000907D 1E push ds 0 0000907E C536[0E00] lds si,[ioctlRH+14] 0 00009082 E8[0000] call hash_pwd ; encrypt new default password 0 00009085 1F pop ds 0 00009086 A3[0000] mov [global_password],ax 0 00009089 C3 ret 513 514 %endif 515 516 BDOS_CODE ends 517 518 end === Trace listing source: drdos/bin/fcbs.lst 1 ;title 'FCB - DOS file system FCB support' 2 ; File : $FCBS.ASM$ 3 ; 4 ; Description : 5 ; 6 ; Original Author : DIGITAL RESEARCH 7 ; 8 ; Last Edited By : $CALDERA$ 9 ; 10 ;-----------------------------------------------------------------------; 11 ; Copyright Work of Caldera, Inc. All Rights Reserved. 12 ; 13 ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, 14 ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. 15 ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES 16 ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF 17 ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO 18 ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE 19 ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE 20 ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, 21 ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, 22 ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, 23 ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF 24 ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT 25 ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND 26 ; CIVIL LIABILITY. 27 ;-----------------------------------------------------------------------; 28 ; 29 ; *** Current Edit History *** 30 ; *** End of Current Edit History *** 31 ; $Log$ 32 ; FCBS.A86 1.10 93/11/11 15:38:14 33 ; Chart Master fix - fcb_readblk over > 64k is truncated to 64k and 34 ; error 2 (Segment boundry overlap) is returned 35 ; FCBS.A86 1.9 93/10/18 17:37:06 36 ; fix for >255 open files (PNW Server) 37 ; ENDLOG 38 39 group PCMCODE BDOS_CODE 40 group PCMDATA BDOS_DATA PCMODE_DATA 41 42 ASSUME DS:PCMDATA 43 44 [list -] 50 === Switch to base=00C180h -> "BDOS_DATA" 51 section BDOS_DATA public align=2 class=DATA 52 BDOS_DATA ends 53 === Switch to base=000000h -> "BDOS_CODE" 54 section BDOS_CODE public align=1 class=CODE 55 56 extrn ifn2dhndl:near 57 extrn parse_one:near 58 extrn fdos_entry:near 59 60 Public fdos_exit 61 62 ; TERMINATE CHILD (EXIT) 63 64 ; +----+----+ 65 ; | 24 | 66 ; +----+----+ 67 68 ; entry: 69 ; ------ 70 ; -none- 71 72 ; exit: 73 ; ----- 74 ; -none- 75 76 ; Close down all FCB handles associated with the current PSP 77 ; 78 fdos_exit: 79 ;--------- 0 0000908A 1E push ds 0 0000908B 16 push ss 0 0000908C 1F pop ds ; DS -> PCM_DSEG 0 0000908D 29C0 sub ax,ax ; start with first DHNDL_ 84 fdos_exit10: 0 0000908F E8[0000] call ifn2dhndl ; get DHNDL_ 0 00009092 7238 jc fdos_exit40 ; stop if we have run out 0 00009094 A3[0200] mov [fcb_pb+2],ax ; we may close this IFN 0 00009097 50 push ax 0 00009098 268B0F mov cx,[es:DHNDL_COUNT + bx] ; get the open count 0 0000909B E32A jcxz fdos_exit30 ; skip if nothing to do 0 0000909D A1[0000] mov ax,[current_psp] ; get current PSP 0 000090A0 263B4731 cmp ax,[es:DHNDL_PSP + bx] ; does it belong to this PSP 0 000090A4 7521 jne fdos_exit30 0 000090A6 36A1[0000] mov ax,[ss:machine_id] ; get current process 0 000090AA 263B472F cmp ax,[es:DHNDL_UID + bx] 0 000090AE 7517 jne fdos_exit30 0 000090B0 26F747020080 test word [es:DHNDL_MODE + bx],DHM_FCB 0 000090B6 740A jz fdos_exit20 ; skip close if not FCB 0 000090B8 06 push es 0 000090B9 53 push bx ; save the DHNDL 0 000090BA B83E00 mov ax,MS_X_CLOSE 0 000090BD E8DF04 call fcb_fdos ; make the FDOS do the work 0 000090C0 5B pop bx 0 000090C1 07 pop es ; recover the DHNDL 105 fdos_exit20: 0 000090C2 26C7070000 mov word [es:DHNDL_COUNT + bx],0 ; always free the handle if it's ours 107 fdos_exit30: 0 000090C7 58 pop ax 0 000090C8 FEC0 inc al ; onto next IFN 0 000090CA 75C3 jnz fdos_exit10 111 fdos_exit40: 0 000090CC 1F pop ds 0 000090CD C3 ret 114 115 116 117 118 119 Public fdos_fcb 120 121 ; GENERIC FCB FUNCTION (FCB) 122 123 ; +----+----+----+----+----+----+----+----+ 124 ; | 22 | fcbadr | count | 125 ; +----+----+----+----+----+----+----+----+ 126 ; | func | 127 ; +----+----+ 128 129 ; entry: 130 ; ------ 131 ; fcbadr: FCB address 132 ; count: multi-sector count for read/write 133 ; func: FCB sub-function 134 135 ; exit: 136 ; ----- 137 ; AX: return code or error code ( < 0) 138 139 fdos_fcb: 140 ;-------- 0 000090CE 8B5E02 mov bx,[2 + bp] ; BX -> parameter block 0 000090D1 8B5F08 mov bx,[8 + bx] ; get subfunction code 0 000090D4 D1E3 shl bx,1 ; make it word index 0 000090D6 80EB1E sub bl,15*2 ; adjust to base address 0 000090D9 721E jc fcb_error ; reject if too low 0 000090DB 80FB12 cmp bl,FCB_MAX1 ; is it in 1st block 0 000090DE 720F jb fdos_fcb10 0 000090E0 80EB12 sub bl,(33-24)*2 ; adjust for gap 0 000090E3 7214 jc fcb_error 0 000090E5 80FB1A cmp bl,FCB_MAX2 ; is it in 2nd block 0 000090E8 7205 jb fdos_fcb10 0 000090EA 80EB04 sub bl,(39-37)*2 ; adjust for gap 0 000090ED 720A jc fcb_error 154 fdos_fcb10: 0 000090EF 83FB1E cmp bx,FCB_MAX3 ; check the range 0 000090F2 7305 jae fcb_error ; skip if invalid function 0 000090F4 2EFFA7[7300] jmp [cs:fcb_table + bx] ; call the right function 158 159 fcb_error: 0 000090F9 BBFFFF mov bx,ED_FUNCTION 0 000090FC C3 ret 162 0 000090FD [9900] fcb_table dw fcb_open ; 15-open file 0 000090FF [3001] dw fcb_close ; 16-close file 0 00009101 [6001] dw fcb_first ; 17-find first 0 00009103 [6801] dw fcb_next ; 18-find next 0 00009105 [5801] dw fcb_delete ; 19-delete file 0 00009107 [9E01] dw fcb_read ; 20-read from file 0 00009109 [9901] dw fcb_write ; 21-write to file 0 0000910B [9100] dw fcb_make ; 22-make file 0 0000910D [4D01] dw fcb_rename ; 23-rename file 172 FCB_MAX1 equ (offset $ - offset fcb_table) 0 0000910F [3102] dw fcb_readrand ; 33-read from file 0 00009111 [2C02] dw fcb_writerand ; 34-write to file 0 00009113 [9602] dw fcb_size ; 35-compute file size 0 00009115 [7901] dw fcb_setrecord ; 36-set relative record 177 FCB_MAX2 equ (offset $ - offset fcb_table) 0 00009117 [5102] dw fcb_readblk ; 39-read from file 0 00009119 [4C02] dw fcb_writeblk ; 40-write to file 180 FCB_MAX3 equ (offset $ - offset fcb_table) 181 182 fcb_make: 183 ;-------- 0 0000911B E8C302 call fcb_path_prep ; build pathname 0 0000911E B83C00 mov ax,MS_X_CREAT 0 00009121 EB06 jmp fcb_open_make_common 187 188 fcb_open: 189 ;-------- 0 00009123 E8BB02 call fcb_path_prep ; build pathname 0 00009126 B83D00 mov ax,MS_X_OPEN 192 fcb_open_make_common: 0 00009129 C706[0600]0280 mov word [fcb_pb+6],DHM_RW+DHM_FCB ; open as an FCB for read/write 0 0000912F E86D04 call fcb_fdos ; lets try and open the file 0 00009132 7301 jnc fcb_open10 ; skip if we can't 0 00009134 C3 ret 197 fcb_open10: 0 00009135 E8[0000] call ifn2dhndl ; ES:BX -> DHNDL_ we have opened 0 00009138 1E push ds 0 00009139 06 push es 0 0000913A 53 push bx ; save DHNDL_ 0 0000913B E8E802 call fcb_point ; ES:BX = FCB 0 0000913E 5E pop si 0 0000913F 1F pop ds ; DS:SI -> DHNDL_ 0 00009140 26884718 mov [es:MSF_IFN + bx],al ; store IFN away 0 00009144 26C7470C0000 mov word [es:MSF_BLOCK + bx],0 ; current block number 0 0000914A 26C7470E8000 mov word [es:MSF_RECSIZE + bx],128 ; current logical record size 0 00009150 E83900 call fcb_update ; update misc changing fields 0 00009153 8B4407 mov ax,[DHNDL_DEVOFF + si] 0 00009156 2689471C mov word ptr [es:MSF_DEVPTR + bx],ax 0 0000915A 8B4409 mov ax,[DHNDL_DEVSEG + si] 0 0000915D 2689471E mov word ptr [es:MSF_DEVPTR+2 + bx],ax 0 00009161 8B440B mov ax,[DHNDL_BLK1 + si] 0 00009164 2689471A mov [es:MSF_BLOCK1 + bx],ax 0 00009168 8A4405 mov al,[DHNDL_ATTR + si] 0 0000916B 26884719 mov [es:MSF_IOCTL + bx],al 0 0000916F 268A07 mov al,[es:MSF_DRIVE + bx] ; get drive from FCB 0 00009172 FEC8 dec al ; was absolute drive specified ? 0 00009174 7904 jns fcb_open20 ; if so use it 0 00009176 36A0[0000] mov al,[ss:current_dsk] ; else use default drive 221 fcb_open20: 0 0000917A FEC0 inc al ; make drive 1 rather than 0 based 0 0000917C 268807 mov [es:MSF_DRIVE + bx],al ; drive code 224 %if 0 225 test byte [DHNDL_DATRB + si],DA_VOLUME 226 %else 0 0000917F 36F706[0800]0800 test word [ss:fcb_pb+8],DA_VOLUME 228 %endif 0 00009186 1F pop ds 0 00009187 7531 jnz fcb_close ; don't leave VOL label's open 0 00009189 31DB xor bx,bx ; no errors ! 0 0000918B C3 ret 233 234 235 fcb_update: 236 ;---------- 237 ; On Entry: 238 ; DS:SI -> DHNDL_ 239 ; ES:BX -> FCB 240 ; On Exit: 241 ; DATE/TIME/SIZE/DBLK/DCNT fields updated 242 ; 0 0000918C 8B440D mov ax,[DHNDL_TIME + si] 0 0000918F 26894716 mov [es:MSF_TIME + bx],ax 0 00009193 8B440F mov ax,[DHNDL_DATE + si] 0 00009196 26894714 mov [es:MSF_DATE + bx],ax 0 0000919A 8B4411 mov ax,[DHNDL_SIZELO + si] 0 0000919D 26894710 mov [es:MSF_SIZE + bx],ax 0 000091A1 8B4413 mov ax,[DHNDL_SIZEHI + si] 0 000091A4 26894712 mov [es:MSF_SIZE+2 + bx],ax 0 000091A8 8B441B mov ax,[DHNDL_DBLK + si] 0 000091AB 2689471C mov [es:MSF_DBLK + bx],ax 0 000091AF 8A441F mov al,[DHNDL_DCNTLO + si] 0 000091B2 8A641E mov ah,[DHNDL_DCNTHI + si] 0 000091B5 2689471E mov [es:MSF_DCNT + bx],ax 0 000091B9 C3 ret 257 258 fcb_close: 259 ;--------- 260 ; close file (DOS function 10h) 0 000091BA E86902 call fcb_point ; ES:BX -> FCB 0 000091BD B0FF mov al,0FFh 0 000091BF 263A4718 cmp al,[es:MSF_IFN + bx] ; is it a multiple close ? 0 000091C3 740F je fcb_fdos_common10 ; don't re-open for this... 0 000091C5 E8A201 call fcb_handle_vfy ; verify we have a sensible handle 0 000091C8 26884718 mov [es:MSF_IFN + bx],al ; mark FCB as closed (it will be) 0 000091CC B83E00 mov ax,MS_X_CLOSE ; now close it 268 ; jmp fcb_fdos_common 269 270 fcb_fdos_common: 271 ;--------------- 0 000091CF E8CD03 call fcb_fdos ; make the FDOS do the work 0 000091D2 7202 jc fcb_fdos_common20 ; return any error codes 274 fcb_fdos_common10: 0 000091D4 31DB xor bx,bx ; else return zero 276 fcb_fdos_common20: 0 000091D6 C3 ret 278 279 280 281 fcb_rename: 282 ;---------- 0 000091D7 E80702 call fcb_path_prep 0 000091DA E8EE01 call fcb_path2_prep 0 000091DD B85600 mov ax,MS_X_RENAME ; it's a rename 0 000091E0 EBED jmp fcb_fdos_common 287 288 fcb_delete: 289 ;---------- 0 000091E2 E8FC01 call fcb_path_prep 0 000091E5 B84100 mov ax,MS_X_UNLINK ; it's a delete 0 000091E8 EBE5 jmp fcb_fdos_common 293 294 295 fcb_first: 296 ;--------- 0 000091EA E8F401 call fcb_path_prep ; prepare pathname 0 000091ED B84E00 mov ax,MS_X_FIRST ; we want to search 1st 0 000091F0 EB06 jmp fcb_search_common 300 301 fcb_next: 302 ;-------- 0 000091F2 E89003 call fcb_restore_search_state 0 000091F5 B84F00 mov ax,MS_X_NEXT 305 fcb_search_common: 0 000091F8 E8F502 call fcb_search ; 0 of OK, otherwise ED_.. 0 000091FB 7205 jc fcb_search_common10 0 000091FD E81503 call fcb_save_search_state ; save sucessful state 0 00009200 31DB xor bx,bx ; return code in BX 310 fcb_search_common10: 0 00009202 C3 ret 312 313 314 fcb_setrecord: 315 ;------------- 0 00009203 E82002 call fcb_point ; ES:BX -> FCB 0 00009206 B88000 mov ax,128 ; multiply current block by 128 0 00009209 26F7670C mul word [es:MSF_BLOCK + bx] ; to give current record number 0 0000920D 31C9 xor cx,cx 0 0000920F 268A4F20 mov cl,[es:MSF_CR + bx] ; Add in the current record 0 00009213 01C8 add ax,cx ; to DX:AX to give the 0 00009215 83D200 adc dx,0 ; relative record 0 00009218 26894721 mov [es:MSF_RR + bx],ax ; save the result 0 0000921C 26885723 mov [es:MSF_RR2 + bx],dl 0 00009220 31DB xor bx,bx ; we did OK 0 00009222 C3 ret 327 328 fcb_write: 329 ;--------- 0 00009223 B84000 mov ax,MS_X_WRITE ; make it a write 0 00009226 EB03 jmp fcb_seq_rw 332 333 fcb_read: 334 ;-------- 0 00009228 B83F00 mov ax,MS_X_READ ; make it a read 336 fcb_seq_rw: 0 0000922B E83C01 call fcb_handle_vfy ; verify we have a sensible handle 0 0000922E 50 push ax ; save the operation 0 0000922F E80402 call fcb_get_count ; AX = bytes to read 0 00009232 50 push ax ; save byte count 0 00009233 E86402 call fcb_seek_seq ; Seek to position in the file 0 00009236 59 pop cx ; recover byte to xfer 0 00009237 58 pop ax ; and the Operation Code 0 00009238 720A jc fcb_seq_rw10 0 0000923A E80800 call fcb_rw ; do the Op 0 0000923D 7205 jc fcb_seq_rw10 0 0000923F 53 push bx ; save the error code 0 00009240 E80102 call fcb_update_seq ; update FCB filepos 0 00009243 5B pop bx ; recover error 350 fcb_seq_rw10: 0 00009244 C3 ret 352 353 fcb_rw: 354 ; On Entry: 355 ; AX = operation code 356 ; CX = count 357 ; fcb_pb+2 = IFN 358 ; On Exit: 359 ; BX = error code 0 00009245 36C416[0000] les dx,[ss:dma_offset] 0 0000924A 01D1 add cx,dx ; see if we overflow 0 0000924C 7236 jc fcb_rw20 0 0000924E 29D1 sub cx,dx ; count back to normal 0 00009250 51 push cx ; save target count 0 00009251 8916[0400] mov [fcb_pb+4],dx 0 00009255 8C06[0600] mov [fcb_pb+6],es ; setup buffer address 0 00009259 890E[0800] mov [fcb_pb+8],cx ; and target count 0 0000925D E83F03 call fcb_fdos ; ask the FDOS to do the read/write 0 00009260 7220 jc fcb_rw10 ; we got a real error... 0 00009262 1E push ds 0 00009263 06 push es 0 00009264 A1[0200] mov ax,[fcb_pb+2] ; get IFN 0 00009267 E8[0000] call ifn2dhndl ; ES:BX -> DHNDL_ we have open 0 0000926A 06 push es 0 0000926B 53 push bx ; save DHNDL_ 0 0000926C E8B701 call fcb_point ; ES:BX = FCB 0 0000926F 5E pop si 0 00009270 1F pop ds ; DS:SI -> DHNDL_ 0 00009271 E818FF call fcb_update ; update file size/time-stamp 0 00009274 07 pop es 0 00009275 1F pop ds 0 00009276 58 pop ax ; recover target count 0 00009277 8B0E[0800] mov cx,[fcb_pb+8] ; we xfered this much 0 0000927B 39C1 cmp cx,ax ; did we xfer enough 0 0000927D 7209 jb fcb_rw30 ; nope.. 0 0000927F 31DB xor bx,bx ; xfer went OK 0 00009281 C3 ret 388 389 fcb_rw10: 0 00009282 58 pop ax ; discard target count 0 00009283 C3 ret 392 393 fcb_rw20: 394 ; Our DTA is too small - return 2 0 00009284 BB0200 mov bx,2 ; indicate the DTA is too small 396 ; stc ; error - don't update FCB 0 00009287 C3 ret 398 399 fcb_rw30: 400 ; We have some form of EOF - lets look into it 0 00009288 E89B01 call fcb_point ; ES:BX = FCB 0 0000928B 268B5F0E mov bx,[es:MSF_RECSIZE + bx] ; BX = record size 0 0000928F 89C8 mov ax,cx 0 00009291 31D2 xor dx,dx ; DX:AX = bytes xfer'd 0 00009293 F7F3 div bx ; did we xfer a complete 0 00009295 85D2 test dx,dx ; number of records ? 0 00009297 7419 jz fcb_rw40 ; if so return 1 408 ; Partial data was read - fill out with zero's and return 3 0 00009299 40 inc ax ; allow for incomplete record 0 0000929A 50 push ax ; save rounded up xfer count 0 0000929B 36C43E[0000] les di,[ss:dma_offset] 0 000092A0 01CF add di,cx ; point to 1st byte after xfer 0 000092A2 89D9 mov cx,bx ; this many in a record 0 000092A4 29D1 sub cx,dx ; so this many weren't xfer'd 0 000092A6 31C0 xor ax,ax ; fill them with zero's 0 000092A8 F3AA rep stosb ; zap the bytes we didn't xfer to 0 000092AA 58 pop ax ; recover xfer count 0 000092AB F7E3 mul bx ; and work out # bytes xfered 0 000092AD 91 xchg ax,cx ; return bytes in CX 0 000092AE BB0300 mov bx,3 ; indicate EOF (partial read) 421 ; clc ; update FCB 0 000092B1 C3 ret 423 424 fcb_rw40: 425 ; No Data was xfered - return 1 0 000092B2 BB0100 mov bx,1 ; indicate EOF (no data read) 427 ; clc ; update FCB 0 000092B5 C3 ret 429 430 fcb_writerand: 431 ;------------- 0 000092B6 B84000 mov ax,MS_X_WRITE ; make it a write 0 000092B9 EB03 jmp fcb_random_rw 434 435 fcb_readrand: 436 ;------------ 0 000092BB B83F00 mov ax,MS_X_READ ; make it a read 438 fcb_random_rw: 0 000092BE E8A900 call fcb_handle_vfy ; check the handle is OK 0 000092C1 50 push ax ; save the code 0 000092C2 E87101 call fcb_get_count ; AX = bytes to read 0 000092C5 50 push ax ; save byte count 0 000092C6 31C9 xor cx,cx ; cause update of seq posn from 0 000092C8 E8A101 call fcb_update_rr ; random record position 0 000092CB E8ED01 call fcb_seek_rr ; Seek to position in the file 0 000092CE 59 pop cx ; recover byte to xfer 0 000092CF 58 pop ax ; and the Operation Code 0 000092D0 7203 jc fcb_random_rw10 0 000092D2 E870FF call fcb_rw ; do the Op 450 fcb_random_rw10: 0 000092D5 C3 ret 452 453 454 fcb_writeblk: 455 ;------------ 0 000092D6 B84000 mov ax,MS_X_WRITE ; make it a write 0 000092D9 EB03 jmp fcb_block_rw 458 459 fcb_readblk: 460 ;----------- 0 000092DB B83F00 mov ax,MS_X_READ ; make it a read 462 fcb_block_rw: 0 000092DE E88900 call fcb_handle_vfy ; check the handle is OK 0 000092E1 50 push ax ; save the code 0 000092E2 E85101 call fcb_get_count ; AX = bytes per record, CX = # records 0 000092E5 91 xchg ax,cx ; CX = bytes per record 0 000092E6 F7E1 mul cx ; AX = bytes to xfer 0 000092E8 85D2 test dx,dx ; more than 64K ? 0 000092EA 740F jz fcb_block_rw10 ; then we should truncate it 0 000092EC B80F00 mov ax,15 ; AX = handy mask 0 000092EF 99 cwd ; DX = 0 0 000092F0 362306[0000] and ax,[ss:dma_offset] ; get dma offset for para 0 000092F5 F7D0 not ax ; DX/AX = maximum bytes we can xfer 0 000092F7 F7F1 div cx ; AX = maximum blocks we can xfer 0 000092F9 F7E1 mul cx ; AX = bytes to xfer (now < 64K) 476 fcb_block_rw10: 0 000092FB 50 push ax ; save byte count 0 000092FC E8BC01 call fcb_seek_rr ; Seek to position in the file 0 000092FF 59 pop cx ; recover byte to xfer 0 00009300 58 pop ax ; and the Operation Code 0 00009301 721C jc fcb_block_rw20 0 00009303 E83FFF call fcb_rw ; do the Op 0 00009306 7217 jc fcb_block_rw20 0 00009308 53 push bx ; save the error code 0 00009309 E86001 call fcb_update_rr ; update FCB filepos, get records xferd 0 0000930C 8B5E02 mov bx,[2 + bp] ; BX -> parameter block 0 0000930F 874F06 xchg cx,[6 + bx] ; update amount xfered 0 00009312 2B4F06 sub cx,[6 + bx] ; CX = # we didn't xfer (normally 0) 0 00009315 5B pop bx ; recover (possible) error 0 00009316 E307 jcxz fcb_block_rw20 ; skip if we read all we wanted to 0 00009318 85DB test bx,bx ; did we have a partial read for 0 0000931A 7503 jnz fcb_block_rw20 ; a reason like EOF ? 0 0000931C BB0200 mov bx,2 ; no, we must have truncated it 494 fcb_block_rw20: 0 0000931F C3 ret 496 497 498 fcb_size: 499 ;-------- 0 00009320 E8BE00 call fcb_path_prep 0 00009323 B84300 mov ax,MS_X_CHMOD ; it's a get info 0 00009326 C706[0600]0000 mov word [fcb_pb+6],0 0 0000932C E87002 call fcb_fdos 0 0000932F 7238 jc fcb_size40 0 00009331 E8F200 call fcb_point ; ES:BX = FCB 0 00009334 268B4F0E mov cx,[es:MSF_RECSIZE + bx] ; get the record size 0 00009338 85C9 test cx,cx ; is it non-zero ? 0 0000933A 7503 jnz fcb_size10 ; if not 0 0000933C B98000 mov cx,128 ; make it 128 bytes 510 fcb_size10: 0 0000933F A1[0A00] mov ax,[fcb_pb+10] 0 00009342 8B16[0C00] mov dx,[fcb_pb+12] ; DX:AX = file length in bytes 0 00009346 E87402 call div_32 ; DX:AX = file length in records 0 00009349 E306 jcxz fcb_size20 ; was there an overflow 0 0000934B 83C001 add ax,1 0 0000934E 83D200 adc dx,0 ; include an extra record 517 fcb_size20: 0 00009351 E8D200 call fcb_point ; ES:BX = FCB 0 00009354 26894721 mov [es:MSF_RR + bx],ax ; low word of size 0 00009358 26885723 mov [es:MSF_RR2 + bx],dl ; hi byte of size 0 0000935C 26837F0E40 cmp word [es:MSF_RECSIZE + bx],64 ; if record size < 64 bytes 0 00009361 7304 jae fcb_size30 ; then we use a 4 byte 0 00009363 26887724 mov [es:MSF_RR2+1 + bx],dh ; random record position 524 fcb_size30: 0 00009367 31DB xor bx,bx ; good return 526 fcb_size40: 0 00009369 C3 ret 528 529 530 ; Utility FCB subroutines 531 ;======================== 532 533 fcb_handle_vfy: 534 ;-------------- 535 ; Verify FCB is valid and open, do not return if it isn't 536 ; nb. Called with nothing on stack 537 ; 538 ; On Entry: 539 ; FCB address in parameter block 540 ; On Exit: 541 ; AX preserved 542 ; ES:BX -> FCB (skipping EXT bit if present) 543 ; fcb_pb+2 = IFN of handle 544 ; On Error - blow away caller and return error in BX 545 ; 546 547 ; DEBUG - on reopen we could do more checks to ensure we are re-opening the 548 ; same file 0 0000936A 50 push ax 0 0000936B E8B800 call fcb_point 0 0000936E 26837F0E00 cmp word [es:MSF_RECSIZE + bx],0 0 00009373 7506 jne fcb_handle_vfy10 0 00009375 26C7470E8000 mov word [es:MSF_RECSIZE + bx],128 554 fcb_handle_vfy10: 0 0000937B 268A4718 mov al,[es:MSF_IFN + bx] ; get IFN 0 0000937F E8[0000] call ifn2dhndl ; ES:BX -> DHNDL_ 0 00009382 720E jc fcb_handle_vfy20 ; it must be a valid IFN 0 00009384 26F747020080 test word [es:DHNDL_MODE + bx],DHM_FCB 0 0000938A 7406 jz fcb_handle_vfy20 ; it must be an FCB.. 0 0000938C 26833F00 cmp word [es:DHNDL_COUNT + bx],0 0 00009390 7520 jne fcb_handle_vfy30 ; it must also be open.. 562 fcb_handle_vfy20: 0 00009392 E89100 call fcb_point 0 00009395 26FF770E push word [es:MSF_RECSIZE + bx] ; save current record size 0 00009399 26FF770C push word [es:MSF_BLOCK + bx] ; save current block number 0 0000939D 06 push es 0 0000939E 53 push bx 0 0000939F E881FD call fcb_open ; try to re-open the file 0 000093A2 5B pop bx 0 000093A3 07 pop es ; point back at FCB 0 000093A4 268F470C pop word [es:MSF_BLOCK + bx] ; restore current block number 0 000093A8 268F470E pop word [es:MSF_RECSIZE + bx] ; restore record size 0 000093AC 720F jc fcb_handle_err 0 000093AE 268A4718 mov al,[es:MSF_IFN + bx] ; get new IFN 575 fcb_handle_vfy30: 0 000093B2 30E4 xor ah,ah 0 000093B4 A3[0200] mov [fcb_pb+2],ax ; set parameter block accordingly 0 000093B7 E86C00 call fcb_point ; ES:BX -> MSF_ 0 000093BA 58 pop ax 0 000093BB F8 clc 0 000093BC C3 ret 582 583 fcb_handle_err: 0 000093BD 83C404 add sp,2*2 ; discard AX and near return address 0 000093C0 83F8FC cmp ax,ED_HANDLE ; if we have run out of handles then 0 000093C3 7503 jne fcb_handle_err10 ; say no FCB's, else return error 0 000093C5 B8DDFF mov ax,ED_NOFCBS 588 fcb_handle_err10: 0 000093C8 93 xchg ax,bx ; error code in BX 0 000093C9 F9 stc 0 000093CA C3 ret 592 593 594 fcb_path2_prep: 595 ;-------------- 596 ; On Entry: 597 ; FCB address in parameter block 598 ; On Exit: 599 ; ES:BX -> FCB (skipping EXT bit if present) 600 ; fcb_pb+6/8 -> unparse name from FCB 601 ; 0 000093CB E85800 call fcb_point ; point at the FCB 0 000093CE 268A07 mov al,[es:MSF_DRIVE + bx] ; get drive 0 000093D1 83C310 add bx,16 ; point at 2nd name in FCB 0 000093D4 BF[0000] mov di,offset fcb_path2 0 000093D7 893E[0600] mov [fcb_pb+6],di 0 000093DB 8C1E[0800] mov [fcb_pb+8],ds ; point at buffer we want 0 000093DF EB26 jmp fcb_path_prep_common 609 610 fcb_path_prep: 611 ;------------- 612 ; On Entry: 613 ; FCB address in parameter block 614 ; On Exit: 615 ; ES:BX -> FCB (skipping EXT bit if present) 616 ; fcb_pb+2/4 -> unparse name from FCB 617 ; 0 000093E1 31C0 xor ax,ax ; assume no attribute 0 000093E3 8B5E02 mov bx,[2 + bp] ; BX -> parameter block 0 000093E6 C45F02 les bx,[2 + bx] ; ES:BX -> FCB 0 000093E9 26803FFF cmp byte [es:MSF_EXTFLG + bx],0ffh ; is it an extended FCB 0 000093ED 7507 jne fcb_path_prep10 0 000093EF 260A4706 or al,[es:MSF_ATTRIB + bx] ; we can use file mode from XFCB 0 000093F3 83C307 add bx,7 ; skip EXT bit of FCB 625 fcb_path_prep10: 0 000093F6 A3[0800] mov [fcb_pb+8],ax ; remember the attribute 0 000093F9 268A07 mov al,[es:MSF_DRIVE + bx] ; get drive 0 000093FC BF[0000] mov di,offset fcb_path 0 000093FF 893E[0200] mov [fcb_pb+2],di 0 00009403 8C1E[0400] mov [fcb_pb+4],ds ; point at buffer we want 631 fcb_path_prep_common: 0 00009407 FEC8 dec al ; 0 = default drive 0 00009409 7903 jns fcb_path_prep20 0 0000940B A0[0000] mov al,[current_dsk] ; use default drive 635 fcb_path_prep20: 0 0000940E 1E push ds 0 0000940F 1E push ds 0 00009410 06 push es 0 00009411 1F pop ds 0 00009412 07 pop es ; ES:DI -> name buffer 0 00009413 0441 add al,'A' ; make drive ASCII 0 00009415 AA stosb 0 00009416 B03A mov al,':' 0 00009418 AA stosb ; now we have 'd:' 0 00009419 8D7701 lea si,[MSF_NAME + bx] ; DS:SI -> source name 0 0000941C A5 movsw 0 0000941D A5 movsw 0 0000941E A5 movsw 0 0000941F A5 movsw ; copy the name leaving spaces intact 0 00009420 B02E mov al,'.' 0 00009422 AA stosb 0 00009423 A5 movsw 0 00009424 A4 movsb ; copy the extention 0 00009425 1F pop ds 655 ; jmp fcb_point ; point ES:BX at FCB again 656 657 658 fcb_point: 659 ;--------- 660 ; On Entry: 661 ; FCB address in parameter block 662 ; On Exit: 663 ; ES:BX -> FCB (skipping EXT bit if present) 664 ; (All other regs preserved) 665 ; 0 00009426 8B5E02 mov bx,[2 + bp] ; BX -> parameter block 0 00009429 C45F02 les bx,[2 + bx] ; ES:BX -> FCB 0 0000942C 26803FFF cmp byte [es:MSF_EXTFLG + bx],0ffh ; is it an extended FCB 0 00009430 7503 jne fcb_point10 0 00009432 83C307 add bx,7 ; skip EXT bit of FCB 671 fcb_point10: 0 00009435 C3 ret 673 674 fcb_get_count: 675 ;------------- 676 ; On Entry: 677 ; none 678 ; On Exit: 679 ; AX = bytes per record 680 ; CX = callers CX count 681 ; All regs fair game 682 ; 0 00009436 E8EDFF call fcb_point ; ES:BX -> FCB 0 00009439 8B7602 mov si,[2 + bp] ; SI -> parameter block 0 0000943C 8B4C06 mov cx,[6 + si] ; CX = count 0 0000943F 268B470E mov ax,[es:MSF_RECSIZE + bx] ; get record size 0 00009443 C3 ret 688 689 fcb_update_seq: 690 ;-------------- 691 ; On Entry: 692 ; CX = byte count actually transferred 693 ; On Exit: 694 ; CX = record count transferred 695 ; All other regs fair game 696 ; CR/BLOCK updated with new value 697 ; 0 00009444 89C8 mov ax,cx 0 00009446 31D2 xor dx,dx ; DX:AX = byte count transfered 0 00009448 E8DBFF call fcb_point ; ES:BX -> FCB 0 0000944B 26F7770E div word [es:MSF_RECSIZE + bx] ; make records xfered 0 0000944F 50 push ax ; save records xfered 0 00009450 91 xchg ax,cx ; also in CX for later 0 00009451 B88000 mov ax,128 0 00009454 26F7670C mul word [es:MSF_BLOCK + bx] ; DX:AX = record of block 0 00009458 01C8 add ax,cx 0 0000945A 83D200 adc dx,0 ; add in amount just xfered 0 0000945D 268A4F20 mov cl,[es:MSF_CR + bx] 0 00009461 30ED xor ch,ch ; now add in CR as a word 0 00009463 01C8 add ax,cx 0 00009465 83D200 adc dx,0 ; DX:AX = record 0 00009468 88D6 mov dh,dl ; DH:AX = record for common code 0 0000946A EB1C jmp fcb_update_common 714 715 716 fcb_update_rr: 717 ;------------- 718 ; On Entry: 719 ; CX = byte count actually transferred 720 ; On Exit: 721 ; CX = record count transferred 722 ; All other regs fair game 723 ; Random Record and CR/BLOCK updated with new value 724 ; 0 0000946C 91 xchg ax,cx 0 0000946D 31D2 xor dx,dx ; DX:AX = byte count transfered 0 0000946F E8B4FF call fcb_point ; ES:BX -> FCB 0 00009472 26F7770E div word [es:MSF_RECSIZE + bx] ; make records xfered 0 00009476 50 push ax ; save records xfered 0 00009477 26014721 add [es:MSF_RR + bx],ax ; update the RR field 0 0000947B 2680572300 adc byte [es:MSF_RR2 + bx],0 ; and the overflow 0 00009480 268B4721 mov ax,[es:MSF_RR + bx] ; get low part of RR 0 00009484 268A7723 mov dh,[es:MSF_RR2 + bx] ; and the hi part 734 fcb_update_common: 0 00009488 88E2 mov dl,ah ; DX will be block number 0 0000948A D0E0 shl al,1 ; get top bit of CR into CY 0 0000948C 11D2 adc dx,dx ; then into DX 0 0000948E D0E8 shr al,1 ; AL = CR (remember mod 128) 0 00009490 26884720 mov [es:MSF_CR + bx],al ; set the CR field 0 00009494 2689570C mov [es:MSF_BLOCK + bx],dx ; and the block field 0 00009498 59 pop cx ; recover records xfered 0 00009499 C3 ret 743 744 745 fcb_seek_seq: 746 ;------------ 747 ; Seek to position in file indicated by the RR position 748 ; On Entry: 749 ; ES:BX -> FCB_ 750 ; On Exit: 751 ; CY clear if no problem, fcb_pb+2=IFN 752 ; else 753 ; CY set, AX = BX = error code 754 ; All other regs fair game 755 ; 0 0000949A E889FF call fcb_point ; ES:BX -> FCB_ 0 0000949D B88000 mov ax,128 0 000094A0 26F7670C mul word [es:MSF_BLOCK + bx] ; get record in DX:AX 0 000094A4 268A4F20 mov cl,[es:MSF_CR + bx] 0 000094A8 30ED xor ch,ch 0 000094AA 01C8 add ax,cx ; add in CR 0 000094AC 83D200 adc dx,0 ; so DX:AX is really the record 0 000094AF 50 push ax ; save low word of record 0 000094B0 89D0 mov ax,dx 0 000094B2 26F7670E mul word [es:MSF_RECSIZE + bx] ; DX:AX = byte offset in file/10000h 0 000094B6 89C1 mov cx,ax ; save the important word 0 000094B8 58 pop ax ; recover low word of record 0 000094B9 EB13 jmp fcb_seek_common 769 770 fcb_seek_rr: 771 ;----------- 772 ; Seek to position in file indicated by the RR position 773 ; On Entry: 774 ; ES:BX -> FCB_ 775 ; On Exit: 776 ; CY clear if no problem, fcb_pb+2=IFN 777 ; else 778 ; CY set, AX = BX = error code 779 ; All other regs fair game 780 ; 0 000094BB E868FF call fcb_point ; ES:BX -> FCB_ 0 000094BE 268A4723 mov al,[es:MSF_RR2 + bx] 0 000094C2 30E4 xor ah,ah 0 000094C4 26F7670E mul word [es:MSF_RECSIZE + bx] ; DX:AX = byte offset in file/10000h 0 000094C8 89C1 mov cx,ax ; save the important word 0 000094CA 268B4721 mov ax,[es:MSF_RR + bx] 787 fcb_seek_common: 0 000094CE 26F7670E mul word [es:MSF_RECSIZE + bx] ; DX:AX = byte offset in file 0 000094D2 01CA add dx,cx ; add the two bits together 0 000094D4 A3[0400] mov [fcb_pb+4],ax 0 000094D7 8916[0600] mov [fcb_pb+6],dx ; save position 0 000094DB C706[0800]0000 mov word [fcb_pb+8],0 ; seek from start 0 000094E1 31C0 xor ax,ax 0 000094E3 268A4718 mov al,[es:MSF_IFN + bx] ; AX = IFN 0 000094E7 A3[0200] mov [fcb_pb+2],ax ; save IFN 0 000094EA B84200 mov ax,MS_X_LSEEK 0 000094ED E9AF00 jmp fcb_fdos ; try and seek to this position 798 799 800 fcb_search: 801 ;---------- 802 ; On Entry: 803 ; AX = operation to perform 804 ; On Exit: 805 ; AX = 0, or ED_ error code (CY set if error) 0 000094F0 FF36[0000] push word [dma_offset] 0 000094F4 FF36[0000] push word [dma_segment] 0 000094F8 C706[0000][0000] mov word [dma_offset],offset fcb_search_buf 0 000094FE 8C1E[0000] mov [dma_segment],ds 0 00009502 E89A00 call fcb_fdos ; do the search 0 00009505 8F06[0000] pop word [dma_segment] 0 00009509 8F06[0000] pop word [dma_offset] 0 0000950D 85C0 test ax,ax ; was there an error 0 0000950F F9 stc ; assume there was 0 00009510 7802 js fcb_search10 ; return the error 0 00009512 31C0 xor ax,ax ; no problems 817 fcb_search10: 0 00009514 C3 ret 819 820 fcb_save_search_state: 821 ;--------------------- 822 ; On entry DS=PCMODE 823 0 00009515 E80EFF call fcb_point 0 00009518 8D7F01 lea di,[MSF_NAME + bx] ; ES:DI -> FCB name 0 0000951B BE[0000] mov si,offset fcb_search_buf 0 0000951E AC lodsb ; get 1st byte = drive info 0 0000951F B90A00 mov cx,20/2 ; copy 20 bytes to FCB 0 00009522 F3A5 rep movsw ; (the rest of the search template) 0 00009524 AA stosb ; drive info byte follow them 831 0 00009525 C43E[0000] les di,[dma_offset] ; ES:DI -> search state in DMA address 0 00009529 8B7602 mov si,[2 + bp] ; SI -> parameter block 0 0000952C C57402 lds si,[2 + si] ; DS:SI -> FCB_ 0 0000952F 803CFF cmp byte [MSF_EXTFLG + si],0ffh ; extended FCB ? 0 00009532 7505 jne fcb_sss10 0 00009534 B90700 mov cx,7 ; copy extended FCB portions too 0 00009537 F3A4 rep movsb ; we have copied up to name 839 fcb_sss10: 0 00009539 AA stosb ; save drive byte info 0 0000953A 57 push di 0 0000953B B020 mov al,' ' ; space fill name 0 0000953D B90B00 mov cx,11 0 00009540 F3AA rep stosb ; all blanks now 0 00009542 5F pop di 0 00009543 16 push ss 0 00009544 1F pop ds ; DS:SI -> pathname 0 00009545 BE[1E00] mov si,offset fcb_search_buf+1Eh 849 0 00009548 57 push di ; unparse knowing name is good 0 00009549 B90800 mov cx,8 ; length of name field 852 fcb_sss20: 0 0000954C AC lodsb ; treat '.' and '..' specially 0 0000954D 3C2E cmp al,'.' ; is either possible ? 0 0000954F 7505 jne fcb_sss30 ; no, continue as normal 0 00009551 AA stosb ; copy the '.' 0 00009552 E2F8 loop fcb_sss20 ; go around for another '.' 0 00009554 EB04 jmp fcb_sss40 ; this name is rubbish!! 859 fcb_sss30: 0 00009556 4E dec si ; forget the non '.' 0 00009557 E8[0000] call parse_one ; parse just the name 862 fcb_sss40: 0 0000955A 5F pop di 0 0000955B 83C708 add di,8 ; di -> fcb ext field 0 0000955E 3C2E cmp al,'.' ; do we have an extention ? 0 00009560 7508 jne fcb_sss50 0 00009562 B90300 mov cx,3 ; length of ext field 0 00009565 57 push di 0 00009566 E8[0000] call parse_one ; parse just extension 0 00009569 5F pop di 871 fcb_sss50: 0 0000956A 83C703 add di,3 ; di -> rest of fcb 0 0000956D BE[1500] mov si,offset fcb_search_buf+15h 0 00009570 A4 movsb ; copy the attribute field 0 00009571 31C0 xor ax,ax 876 ; mov cx,10/WORD 0 00009573 B90400 mov cx,8/2 0 00009576 F3AB rep stosw ; 10 bytes of zeros 0 00009578 A1[2900] mov ax,word ptr [srch_buf+21+DBLOCK1H] 0 0000957B AB stosw ; high word of 1st block 0 0000957C A5 movsw ; copy time 0 0000957D A5 movsw ; copy date 0 0000957E A1[2F00] mov ax,word ptr [srch_buf+21+DBLOCK1] 0 00009581 AB stosw ; 1st block 0 00009582 A5 movsw 0 00009583 A5 movsw ; copy filesize 0 00009584 C3 ret 888 889 fcb_restore_search_state: 890 ;------------------------ 891 ; On entry DS=PCMODE 0 00009585 1E push ds 0 00009586 E89DFE call fcb_point ; ES:BX -> FCB_ 0 00009589 06 push es 0 0000958A 1E push ds 0 0000958B 07 pop es 0 0000958C 1F pop ds ; swap DS/ES 0 0000958D BF[0100] mov di,offset fcb_search_buf+1 899 ; ES:DI -> internal state 0 00009590 8D7701 lea si,[1 + bx] ; DS:SI -> FCB+1 0 00009593 B90A00 mov cx,10 0 00009596 F3A5 rep movsw ; copy info from FCB 0 00009598 AC lodsb ; get "drive" info 0 00009599 26A2[0000] mov [es:fcb_search_buf],al ; it's the 1st byte in the srch state 0 0000959D 1F pop ds 0 0000959E C3 ret 907 908 fcb_fdos: 909 ;-------- 910 ; Make an FDOS call (NB. We don't have MX here, so it's OK) 911 ; Set top bit of remote_call flag so we use IFN's not XFN's 912 ; On Entry: 913 ; AX = FDOS operation 914 ; fcb_pb -> FDOS parameter block 915 ; On Exit: 916 ; As FDOS call 917 ; 0 0000959F A3[0000] mov [fcb_pb],ax ; save operation type 0 000095A2 810E[0000]0080 or word [remote_call],DHM_FCB ; forget about PSP during FCB call 0 000095A8 BA[0000] mov dx,offset fcb_pb ; DS:DX -> parameter block 0 000095AB 1E push ds 0 000095AC 55 push bp 0 000095AD E8[0000] call fdos_entry ; call the FDOS 0 000095B0 5D pop bp 0 000095B1 1F pop ds 0 000095B2 8126[0000]FF7F and word [remote_call],(~ DHM_FCB) & 0ffffh ; FCB operation over 0 000095B8 83F8A6 cmp ax,ED_LASTERROR 0 000095BB F5 cmc ; CY set if an error occurred 0 000095BC C3 ret 930 931 div_32: 932 ; Entry: DX,AX = long dividend 933 ; CX = word divisor 934 ; Exit: DX,AX = long result 935 ; CX = remainder 936 0 000095BD E31F jcxz div0 ; divide by 0 0 000095BF 83F901 cmp cx,1 0 000095C2 7420 je div1 ; divide by 1 0 000095C4 57 push di 0 000095C5 53 push bx 0 000095C6 31DB xor bx,bx ; BX = 0 0 000095C8 93 xchg ax,bx ; low word in BX, AX = 0 0 000095C9 92 xchg ax,dx ; high word in DX:AX 0 000095CA 50 push ax ; save high word 0 000095CB F7F1 div cx ; divide high part 0 000095CD 89C7 mov di,ax ; save result 0 000095CF F7E1 mul cx ; AX = even divisor part 0 000095D1 5A pop dx ; old high in DX 0 000095D2 29C2 sub dx,ax ; eliminate even part 0 000095D4 93 xchg ax,bx ; AX = low word 0 000095D5 F7F1 div cx ; low part in AX 0 000095D7 89D1 mov cx,dx ; CX = remainder 0 000095D9 89FA mov dx,di ; high result in DX 0 000095DB 5B pop bx 0 000095DC 5F pop di 0 000095DD C3 ret 958 959 div0: 0 000095DE B8FFFF mov ax,-1 0 000095E1 89C2 mov dx,ax 0 000095E3 C3 ret 963 div1: 0 000095E4 49 dec cx ; CX = remainder = 0 0 000095E5 C3 ret 966 967 BDOS_CODE ends 968 === Switch to base=00C180h -> "PCMODE_DATA" 969 section PCMODE_DATA public align=2 class=DATA 970 971 extrn fcb_pb:word 972 extrn fcb_path:byte 973 extrn fcb_path2:byte 974 extrn fcb_search_buf:byte 975 976 extrn current_dsk:byte 977 extrn current_psp:word 978 extrn dma_offset:word 979 extrn dma_segment:word 980 extrn machine_id:word 981 extrn remote_call:word 982 extrn srch_buf:byte 983 984 PCMODE_DATA ends 985 986 end === Trace listing source: drdos/bin/redir.lst 1 ;title 'REDIR - DOS file system network redirector interace support' 2 ; File : $REDIR.ASM$ 3 ; 4 ; Description : 5 ; 6 ; Original Author : DIGITAL RESEARCH 7 ; 8 ; Last Edited By : $CALDERA$ 9 ; 10 ;-----------------------------------------------------------------------; 11 ; Copyright Work of Caldera, Inc. All Rights Reserved. 12 ; 13 ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, 14 ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. 15 ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES 16 ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF 17 ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO 18 ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE 19 ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE 20 ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, 21 ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, 22 ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, 23 ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF 24 ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT 25 ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND 26 ; CIVIL LIABILITY. 27 ;-----------------------------------------------------------------------; 28 ; 29 ; *** Current Edit History *** 30 ; *** End of Current Edit History *** 31 ; $Log: $ 32 ; REDIR.A86 1.30 94/12/01 10:05:21 33 ; added attribute support for open/move/unlink 34 ; REDIR.A86 1.29 94/11/11 15:10:03 35 ; Code at redir_lseek30 changed to ensure that the file offset is 36 ; updated. Previously, this did not happen when INT 21/4202 (seek from 37 ; end of file) was called, and consequently the game MYST could not 38 ; be installed under NWDOS7. 39 ; REDIR.A86 1.28 94/10/03 15:41:12 40 ; fix problem where VLM network mapping gets deleted if you try to access 41 ; a path greater than 66 characters long on a network drive. 42 ; REDIR.A86 1.27 94/02/22 18:05:09 43 ; fix problem with "d:\\filename.ext" (Netware 4 LOGIN) 44 ; REDIR.A86 1.26 94/01/10 16:42:16 45 ; File delete uses file attributes of 06, not 16 (no directory bit) 46 ; REDIR.A86 1.25 93/12/10 00:03:09 47 ; Move non-inherited bit to correct place in file handle 48 ; REDIR.A86 1.22 93/11/19 23:59:00 49 ; If a read/write returns ED_LOCKFAIL turn into ED_ACCESS on shared files 50 ; REDIR.A86 1.21 93/09/24 19:50:50 51 ; Tidy up code on rename 52 ; REDIR.A86 1.15 93/06/16 16:22:21 53 ; Always initialise file search attributes to 16h (ie. sys+hidden+dir) 54 ; REDIR.A86 1.14 93/06/11 15:08:09 55 ; Return 0 from search first/next 56 ; REDIR.A86 1.13 93/06/11 02:06:53 57 ; zero space adjust on getddsc 58 ; ENDLOG 59 60 group PCMCODE BDOS_CODE 61 group PCMDATA PCMODE_DATA BDOS_DATA 62 63 ASSUME DS:PCMDATA 64 65 [list -] 74 75 FD_EXPAND equ 55h 76 77 === Switch to base=00C180h -> "PCMODE_DATA" 78 section PCMODE_DATA public align=2 class=DATA 79 80 extrn current_dsk:byte 81 extrn current_ddsc:dword 82 extrn current_dhndl:dword 83 extrn current_filepos:dword 84 extrn current_ldt:dword 85 extrn dma_offset:word 86 extrn dma_segment:word 87 extrn err_drv:byte 88 extrn file_attrib:word 89 extrn ldt_ptr:dword 90 extrn last_drv:byte 91 extrn phys_drv:byte 92 extrn pri_pathname:byte 93 extrn remote_call:word 94 extrn sec_pathname:byte 95 extrn srch_buf:byte 96 97 ; Data for some int2f commands 98 99 extrn int2f_cmd:word 100 extrn int2f_stack:word 101 extrn file_mode:word 102 103 PCMODE_DATA ends 104 === Switch to base=00C180h -> "BDOS_DATA" 105 section BDOS_DATA public align=2 class=DATA 106 107 extrn lfn_search_redir:byte 108 109 BDOS_DATA ends 110 === Switch to base=000000h -> "BDOS_CODE" 111 section BDOS_CODE public align=1 class=CODE 112 113 Public islocal 114 Public redir_asciiz_dev_offer 115 Public redir_asciiz_offer 116 Public redir_asciiz_file_offer 117 118 Public redir_drv_offer 119 Public redir_dhndl_offer 120 Public redir_move_offer 121 Public redir_snext_offer 122 123 extrn toupper:near 124 extrn check_delim:near 125 extrn check_slash:near 126 extrn check_dslash:near 127 extrn copy_asciiz:near 128 extrn unparse:near 129 extrn find_xfn:near 130 extrn find_dhndl:near 131 extrn ifn2dhndl:near 132 extrn get_xftptr:near 133 extrn output_hex:near 134 %ifdef KANJI 135 extrn dbcs_lead:near 136 %endif 137 138 139 redir_dhndl_offer: 140 ;================ 141 ; The FDOS has called this hook to see if we are operating on an MSNET drive. 142 ; We return if we are not, or stay and process function here if we are 0 000095E6 26F6470680 test byte ptr [es:DHNDL_WATTR+1 + bx],DHAT_REMOTE/100h 0 000095EB 7501 jnz redir_dhndl_accept 0 000095ED C3 ret 146 redir_dhndl_accept: 147 ; copy some info from DHNDL_ to local variables 0 000095EE 1E push ds 0 000095EF 16 push ss 0 000095F0 1F pop ds 0 000095F1 268B4707 mov ax,[es:DHNDL_DEVOFF + bx] 0 000095F5 A3[0000] mov word ptr [current_ddsc],ax 0 000095F8 268B4709 mov ax,word ptr [es:DHNDL_DEVSEG + bx] 0 000095FC A3[0200] mov word ptr [current_ddsc+2],ax 0 000095FF 268B4715 mov ax,word ptr [es:DHNDL_POS + bx] 0 00009603 A3[0000] mov word ptr [current_filepos],ax 0 00009606 268B4717 mov ax,word ptr [es:DHNDL_POS+2 + bx] 0 0000960A A3[0200] mov word ptr [current_filepos+2],ax 0 0000960D 268B4747 mov ax,word ptr [es:DHNDL_POSX + bx] 0 00009611 A3[0400] mov word ptr [current_filepos+4],ax 0 00009614 268B4749 mov ax,word ptr [es:DHNDL_POSX+2 + bx] 0 00009618 A3[0600] mov word ptr [current_filepos+6],ax 0 0000961B 1F pop ds 0 0000961C EB70 jmp redir_accept ; now we can process the call 165 166 167 redir_asciiz_dev_offer: 168 ;====================== 169 ; The FDOS has called this hook to see if we are opening a redirected device. 170 ; We return if we are not, or stay and process function here if we are 171 172 ; Before we build it all ourselves do the appropriate INT 2F to allow 173 ; other people to process the path themselves 174 0 0000961E E83A01 call redir_dev_check ; is it a device ? 0 00009621 736B jnc redir_accept ; it's been recognised 0 00009623 C3 ret 178 179 redir_move_offer: 180 ;================ 181 ; The FDOS has called this hook to see if the rename operation is on a 182 ; redirected drive. Lantastic relies on the path check broadcast's being 183 ; done in the order new_name, old_name. 184 0 00009624 C706[0000]FFFF mov word [current_ldt],0ffffh 0 0000962A C606[0000]1F mov byte [err_drv],DHAT_DRVMSK 0 0000962F 1E push ds 0 00009630 8B7602 mov si,[2 + bp] ; SI -> parameter block 0 00009633 C5740A lds si,[10 + si] ; DS:SI -> user supplied name 0 00009636 16 push ss 0 00009637 07 pop es 0 00009638 BF[0000] mov di,offset sec_pathname ; DI -> where to build pathname 0 0000963B 1E push ds 0 0000963C 56 push si 0 0000963D 57 push di 0 0000963E 55 push bp 0 0000963F B82311 mov ax,I2F_PPATH 0 00009642 CD2F int 2fh ; offer path build to someone else 0 00009644 5D pop bp 0 00009645 5F pop di 0 00009646 5E pop si 0 00009647 1F pop ds 0 00009648 B90000 mov cx,0 ; if accepted then it's a remote drive 0 0000964B 7303 jnc redir_move_offer10 0 0000964D E82D01 call build_remote_path ; build path if it a remote drive 206 redir_move_offer10: 0 00009650 1F pop ds 0 00009651 721B jc redir_asciiz_error ; return error's if we have any 0 00009653 E301 jcxz redir_asciiz_offer ; it's a valid remote path 0 00009655 C3 ret ; it's not a remote path 211 212 redir_asciiz_offer: 213 ;================== 214 ; The FDOS has called this hook to see if we are operating on an redirected 215 ; drive. We return if we are not, or stay and process function here if we are. 0 00009656 E80201 call redir_dev_check ; is it a device ? 0 00009659 7333 jnc redir_accept ; it's been recognised 218 ; jmp redir_asciiz_file_offer ; now try offering as a file 219 220 redir_asciiz_file_offer: 221 ;======================= 222 ; entry: SS:BP -> function #, parameter address 223 ; 1st level call (MXdisk not owned) 224 ; exit: ZF = 1 if not networked 225 ; 226 ; This function is only called after an Int 2F/I2F_PPATH callout has been 227 ; made and failed. On some functions (Open/Create) we do a check for devices 228 ; between the redir_dev_offer and redir_asciiz_file offer 229 230 ; We look for a "\\" as the start of "\\server\dir\file" form 231 0 0000965B 1E push ds ; save DS 0 0000965C 8B7602 mov si,[2 + bp] ; SI -> parameter block 0 0000965F C57402 lds si,[2 + si] ; get ASCIIZ # from parameter block 0 00009662 BF[0000] mov di,offset pri_pathname ; SS:DI -> path buffer 0 00009665 E81501 call build_remote_path ; build path if it a remote drive 0 00009668 1F pop ds ; restore DS 0 00009669 7203 jc redir_asciiz_error ; return error's if we have any 0 0000966B E321 jcxz redir_accept ; it's a valid remote path 0 0000966D C3 ret ; it's not a remote path 241 242 redir_asciiz_error: 243 ; On Entry: 244 ; BX = error code 245 ; DS on stack 246 ; On Exit: 247 ; DS restored, BX preserved 248 ; near return on stack discarded, and error returned to fdos_entry 249 ; 0 0000966E 58 pop ax ; discard "offer" near ret 0 0000966F C3 ret ; drop straight back to caller 252 253 redir_drv_offer: 254 ;=============== 255 ; The FDOS has called this hook to see if we are operating on an MSNET drive. 256 ; We return if we are not, or stay and process function here if we are 257 ; 258 ; entry: SS:BP -> function #, parameter address 259 ; (MXdisk not owned) 260 ; exit: return if not networked 261 0 00009670 8A16[0000] mov dl,[current_dsk] ; assume it's the default drive 0 00009674 8B7602 mov si,[2 + bp] ; SI -> parameter block 0 00009677 8B4402 mov ax,[2 + si] ; get drive # from parameter block 0 0000967A 84C0 test al,al ; test if default drive 0 0000967C 7402 jz redir_drv_offer10 ; skip if default drive 0 0000967E 48 dec ax ; else decrement for 0..26 0 0000967F 92 xchg ax,dx ; and use that 269 redir_drv_offer10: 0 00009680 E8C700 call isremote 0 00009683 7509 jnz redir_accept 0 00009685 C3 ret ; return if not 273 274 redir_snext_offer: 275 ;================= 276 ; The FDOS has called this hook to see if we are operating on an MSNET drive. 277 ; We return if we are not, or stay and process function here if we are 278 0 00009686 E85604 call redir_restore_srch_state 0 00009689 A880 test al,80h ; MSNET drive ? 0 0000968B 7501 jnz redir_accept 0 0000968D C3 ret 283 284 285 redir_accept: 286 ;============ 287 ; We have decided to accept an FDOS function. 288 ; Note by this time the functions have been validated as legal 0 0000968E C606[0000]FF mov byte [lfn_search_redir], 0FFh 290 0 00009693 C706[0000]1600 mov word [file_attrib],16h ; default search attribs to all 0 00009699 5E pop si ; discard the near return address 0 0000969A 8B7602 mov si,[2 + bp] ; SI -> parameter block 0 0000969D 8B34 mov si,[si] ; fdos code number 0 0000969F 01F6 add si,si ; make it a word offset 0 000096A1 2EFFA4[5200] jmp [cs:si+redir_tbl-(39h*2)] ; call the relevant function 297 298 299 redir_badfunc: 300 ;------------- 0 000096A6 BBFFFF mov bx,ED_FUNCTION ; bad function number 0 000096A9 C3 ret ; (shouldn't get here...) 303 0 000096AA [E101] redir_tbl dw redir_mkdir ; 39-make directory 0 000096AC [E601] dw redir_rmdir ; 3A-remove directory 0 000096AE [F601] dw redir_chdir ; 3B-change directory 0 000096B0 [3702] dw redir_creat ; 3C-create file 0 000096B2 [5902] dw redir_open ; 3D-open file 0 000096B4 [CB02] dw redir_close ; 3E-close file 0 000096B6 [F802] dw redir_read ; 3F-read from file 0 000096B8 [1003] dw redir_write ; 40-write to file 0 000096BA [7603] dw redir_unlink ; 41-delete file 0 000096BC [8103] dw redir_lseek ; 42-set file pointer 0 000096BE [2C04] dw redir_chmod ; 43-get/set file attributes 0 000096C0 [C000] dw redir_badfunc ; 44-IOCTL emulation 0 000096C2 [C000] dw redir_badfunc ; 45-duplicate handle 0 000096C4 [C000] dw redir_badfunc ; 46-force duplicate handle 0 000096C6 [C000] dw redir_badfunc ; 47-get current directory 0 000096C8 [6304] dw redir_getdpb ;*48*disk information 0 000096CA [C000] dw redir_badfunc ;*49*flush buffers 0 000096CC [C000] dw redir_badfunc ;*4A*drive select 0 000096CE [C000] dw redir_badfunc ;*4B*create child PSP 0 000096D0 [C000] dw redir_badfunc ;*4C*close child PSP 0 000096D2 [C000] dw redir_badfunc ;*4D*generic FCB call 0 000096D4 [9804] dw redir_first ; 4E-find first matching file 0 000096D6 [AC04] dw redir_next ; 4F-find next matching file 0 000096D8 [0D05] dw redir_commit ;*50*commit file 0 000096DA [2105] dw redir_mknew ;*51*make new file 0 000096DC [3D05] dw redir_lock ;*52*lock/unlock block 0 000096DE [C000] dw redir_badfunc ; 53 build DDSC from BPB 0 000096E0 [C000] dw redir_badfunc ;*54*Int 25/26 emulation 0 000096E2 [5805] dw redir_expand ; 55 expand file name 0 000096E4 [6705] dw redir_move ; 56-rename file 0 000096E6 [6D05] dw redir_dattim ; 57-get/set file name 335 336 Public get_ldt 337 338 ; To support func5D00 remote server calls we must bypass the LDT and 339 ; go directly to the physical drive. To allow support of CDROM's etc 340 ; on servers we do use the LDT's where no corresonding physical drive 341 ; exists. 342 343 get_ldt: 344 ;------- 345 ; On Entry: 346 ; AL = drive (0 based) 347 ; On Exit: 348 ; ES:BX -> LDT for that drive, set CY if no valid LDT 349 ; (All other regs preserved) 350 ; 0 000096E8 363A06[0000] cmp al,[ss:phys_drv] ; if there is no conflict with 0 000096ED 730E jae get_ldt_raw ; physical drives it's OK 0 000096EF 36F706[0000]FF00 test word [ss:remote_call],0ffh ; remote calls must get to physical 0 000096F6 7405 jz get_ldt_raw ; for server support 0 000096F8 BBF1FF mov bx,ED_DRIVE ; invalid drive 0 000096FB F9 stc ; no-go 0 000096FC C3 ret 358 359 Public get_ldt_raw 360 361 get_ldt_raw: 362 ;----------- 363 ; On Entry: 364 ; AL = drive (0 based) 365 ; On Exit: 366 ; ES:BX -> LDT for that drive, set CY if no valid LDT 367 ; (All other regs preserved) 368 ; 0 000096FD 50 push ax 0 000096FE BBF1FF mov bx,ED_DRIVE ; assume invalid drive 0 00009701 363A06[0000] cmp al,[ss:last_drv] ; do we have an LDT for this drive ? 0 00009706 7314 jae get_ldt10 ; if not we can't have an LDT 0 00009708 36833E[0200]00 cmp word [ss:ldt_ptr+2],0 ; are the LDT's allocated yet ? 0 0000970E 740C je get_ldt10 ; if not return an error 0 00009710 B358 mov bl,LDT_LEN 0 00009712 F6E3 mul bl ; AX = offset of LDT entry for drive 0 00009714 36C41E[0000] les bx,[ss:ldt_ptr] ; get base of LDT's 0 00009719 01C3 add bx,ax ; DS:BX -> LDT for this drive 0 0000971B F9 stc ; ie. CLC on exit 380 get_ldt10: 0 0000971C F5 cmc 0 0000971D 58 pop ax 0 0000971E C3 ret 384 385 get_ldt_flags: 386 ;------------- 387 ; entry: DL = drive number 388 ; exit: AX = LDT_FLAGS entry for that drive 389 ; (All other regs preserved) 390 ; 0 0000971F 06 push es 0 00009720 53 push bx 0 00009721 31C0 xor ax,ax ; assume no LDT around... 0 00009723 92 xchg ax,dx ; AL = drive number 0 00009724 E8C1FF call get_ldt ; ES:BX -> LDT 0 00009727 92 xchg ax,dx ; restore drive to DX 0 00009728 720E jc glf10 ; AX = zero if no LDT 0 0000972A 36891E[0000] mov word ptr [ss:current_ldt],bx ; set current_ldt 0 0000972F 368C06[0200] mov word ptr [ss:current_ldt+2],es 0 00009734 268B4743 mov ax,[es:LDT_FLAGS + bx] ; return real flags 401 glf10: 0 00009738 5B pop bx 0 00009739 07 pop es 0 0000973A C3 ret 405 406 islocal: 407 ;------- 408 ; entry: AL = drive number (zero based) 409 ; exit: CY = set if drive is remote 410 ; (All other regs preserved) 411 ; 0 0000973B 50 push ax 0 0000973C 52 push dx 0 0000973D 92 xchg ax,dx 0 0000973E E8DEFF call get_ldt_flags 416 %ifdef JOIN 0 00009741 A900A0 test ax,LFLG_JOINED+LFLG_NETWRKD 418 ; are REMOTE/JOINED bits set ? 419 %else 420 test ax,LFLG_NETWRKD ; is REMOTE bit set ? 421 %endif 0 00009744 7401 jz islocal10 0 00009746 F9 stc ; indicate it's not local 424 islocal10: 0 00009747 5A pop dx 0 00009748 58 pop ax 0 00009749 C3 ret 428 429 isremote: 430 ;-------- 431 ; entry: DL = drive number 432 ; exit: ZF = clear if drive is remote 433 ; CY = set if drive is JOIN'd 434 ; (Only AX corrupted) 435 ; 0 0000974A E8D2FF call get_ldt_flags 437 %ifdef JOIN 0 0000974D A90020 test ax,LFLG_JOINED ; is JOINED bit set ? 0 00009750 7504 jnz isremote10 440 %endif 0 00009752 A90080 test ax,LFLG_NETWRKD ; is REMOTE bit set ? 0 00009755 C3 ret 443 %ifdef JOIN 444 isremote10: 0 00009756 A90080 test ax,LFLG_NETWRKD ; is REMOTE bit set ? 0 00009759 F9 stc ; STC to indicate JOIN'd 0 0000975A C3 ret 448 %endif 449 450 redir_dev_check: 451 ;--------------- 452 ; Offer the name to the network as a device 453 ; On Entry: 454 ; PB+2 = dword ptr to ascii name 455 ; DI -> buffer to parse into 456 ; On Exit: 457 ; CY set if not recognised 458 ; 0 0000975B C706[0000]FFFF mov word [current_ldt],0ffffh 0 00009761 C606[0000]1F mov byte [err_drv],DHAT_DRVMSK 0 00009766 1E push ds 0 00009767 55 push bp 0 00009768 8B7602 mov si,[2 + bp] ; SI -> parameter block 0 0000976B C57402 lds si,[2 + si] ; DS:SI -> user supplied name 0 0000976E 89F2 mov dx,si ; DS:DX as well.. 0 00009770 16 push ss 0 00009771 07 pop es 0 00009772 BF[0000] mov di,offset pri_pathname ; DI -> where to build pathname 0 00009775 B82311 mov ax,I2F_PPATH 0 00009778 CD2F int 2fh ; offer path build to someone else 0 0000977A 5D pop bp 0 0000977B 1F pop ds 0 0000977C C3 ret 474 475 build_remote_path: 476 ;----------------- 477 ; On Entry: 478 ; DS:SI -> path to check 479 ; SS:DI -> position to build remote path 480 ; On Exit: 481 ; CY clear, CX == 0 if it's a valid remote path 482 ; CY clear, CX <> 0 if it's a local path 483 ; CY set if there is an error to be returned (BX = error code) 484 ; 0 0000977D 89F1 mov cx,si ; save source path in CX 0 0000977F 368A16[0000] mov dl,[ss:current_dsk] ; assume current disk 0 00009784 AD lodsw ; get 1st two characters 0 00009785 84C0 test al,al ; make sure it's not a NUL string 0 00009787 7419 jz build_remote_path10 ; before we check it it's a 0 00009789 80FC3A cmp ah,':' ; drive specified 0 0000978C 7514 jne build_remote_path10 ; we want to find "d:\\" format too 0 0000978E BBF1FF mov bx,ED_DRIVE ; assume "invalid drive" error 0 00009791 24DF and al,~ ('a'-'A') ; cheap upper case 0 00009793 2C41 sub al,'A' 0 00009795 722E jb build_remote_path30 ; return "invalid drive" if error 0 00009797 363A06[0000] cmp al,[ss:last_drv] ; check if > 'Z' 0 0000979C 7727 ja build_remote_path30 ; return "invalid drive" if error 0 0000979E 92 xchg ax,dx ; DL = ASCIIZ supplied drive 0 0000979F AD lodsw ; get possible '\\' 0 000097A0 EB0C jmp build_remote_path15 501 build_remote_path10: 0 000097A2 36C706[0000]FFFF mov word [ss:current_ldt],0ffffh 0 000097A9 E8[0000] call check_dslash ; is it "\\" 0 000097AC 740B je build_remote_path20 ; if so forget about the drive # 505 build_remote_path15: 0 000097AE E899FF call isremote ; test if drive DL is remote 507 %ifdef JOIN 0 000097B1 7212 jb build_remote_path30 ; return "invalid drive" if JOINed 509 %endif 0 000097B3 7504 jnz build_remote_path20 ; it's remote, go build a path 0 000097B5 31C9 xor cx,cx ; CY clear (no error) 0 000097B7 41 inc cx ; CX <> 0, (non-remote drive) 0 000097B8 C3 ret 514 515 build_remote_path20: 516 ; Build a path from the CSD and the pathname in the parameter block 0 000097B9 89CE mov si,cx ; DS:SI -> source ASIIZ name 0 000097BB 16 push ss 0 000097BC 07 pop es ; ES:DI -> MSNET buffer 0 000097BD E8CF03 call redir_build_path 0 000097C0 7203 jc build_remote_path30 0 000097C2 31C9 xor cx,cx ; CY clear, CX == 0 0 000097C4 C3 ret ; it's a valid remote path 524 525 build_remote_path30: 0 000097C5 F9 stc ; CY set, we have error BX 0 000097C6 C3 ret 528 529 530 531 ; MAKE DIRECTORY (MKDIR) 532 533 ; +----+----+----+----+----+----+ 534 ; | 39 | name | 535 ; +----+----+----+----+----+----+ 536 537 ; entry: 538 ; ------ 539 ; name: segmented address of ASCIIZ name 540 541 ; exit: 542 ; ----- 543 ; BX: 0000 or error code ( < 0) 544 545 redir_mkdir: 0 000097C7 B80311 mov ax,I2F_MKDIR ; it's a make dir 0 000097CA EB03 jmp redir_pathop_common 548 549 550 ; REMOVE DIRECTORY (RMDIR) 551 552 ; +----+----+----+----+----+----+ 553 ; | 3A | name | 554 ; +----+----+----+----+----+----+ 555 556 ; entry: 557 ; ------ 558 ; name: segmented address of ASCIIZ name 559 560 ; exit: 561 ; ----- 562 ; BX: 0000 or error code ( < 0) 563 564 565 redir_rmdir: 0 000097CC B80111 mov ax,I2F_RMDIR ; it's a remove dir 567 ; jmp redir_pathop_common 568 569 redir_pathop_common: 0 000097CF 1E push ds 0 000097D0 16 push ss 0 000097D1 1F pop ds 0 000097D2 E82005 call int2f_ldt 0 000097D5 1F pop ds 0 000097D6 7202 jc redir_pathop_common10 0 000097D8 31C0 xor ax,ax ; no problems 577 redir_pathop_common10: 0 000097DA 93 xchg ax,bx ; return result in BX 0 000097DB C3 ret 580 581 582 583 ; CHANGE DIRECTORY (CHDIR) 584 585 ; +----+----+----+----+----+----+ 586 ; | 3B | name | 587 ; +----+----+----+----+----+----+ 588 589 ; entry: 590 ; ------ 591 ; name: segmented address of ASCIIZ name 592 593 ; exit: 594 ; ----- 595 ; BX: 0000 or error code ( < 0) 596 597 redir_chdir: 598 ;------------ 599 ; The following code throws out the ASSIGN/SUBST form "f:=d:\" 600 ; The alternative is to allow the Extentions to throw it out as a bad path 601 ; but this is safer, and doesn't cost us much. 602 0 000097DC 1E push ds 0 000097DD BBFDFF mov bx,ED_PATH ; assume we have a problem 605 ; BX = ED_PATH ready for error 606 0 000097E0 8B7602 mov si,[2 + bp] ; SI -> parameter block 0 000097E3 C57402 lds si,[2 + si] ; DS:SI -> ASCIIZ string 0 000097E6 817C013A3D cmp word ptr [1 + si],':=' ; 'd:=' specification? ; NASM port swapped text literals 0 000097EB 742E je redir_chdir40 611 0 000097ED 16 push ss 0 000097EE 1F pop ds ; DS = PCMODE 614 0 000097EF 833E[0000]FF cmp word [current_ldt],-1 0 000097F4 7425 je redir_chdir40 ; we reject any chdir of the form 617 ; "\\server\path" 0 000097F6 B80511 mov ax,I2F_CHDIR 0 000097F9 E8F904 call int2f_ldt ; is this a valid path ? 0 000097FC 721C jc redir_chdir30 0 000097FE 1E push ds 0 000097FF 07 pop es 0 00009800 BE[0000] mov si,offset pri_pathname 624 625 ; DGM - don't allow path greater than 66 chars 0 00009803 B94300 mov cx, LDT_FLAGS-LDT_NAME ; calculate max pathlen from LDT 0 00009806 89F7 mov di, si 0 00009808 29C0 sub ax,ax 0 0000980A F2AE repne scasb 0 0000980C B8FDFF mov ax, ED_PATH ; assume path too long 0 0000980F 7509 jne redir_chdir30 ; jump if path too long 632 0 00009811 C43E[0000] les di,[current_ldt] ; ES:DI -> path for this drive 0 00009815 E8[0000] call copy_asciiz ; copy new path to LDT current dir 0 00009818 31C0 xor ax,ax ; no errors 636 redir_chdir30: 0 0000981A 93 xchg ax,bx ; return result in BX 638 redir_chdir40: 0 0000981B 1F pop ds 0 0000981C C3 ret 641 642 643 ; CREATE FILE (CREAT) 644 645 ; +----+----+----+----+----+----+----+----+ 646 ; | 3C | name | mode | 647 ; +----+----+----+----+----+----+----+----+ 648 649 ; entry: 650 ; ------ 651 ; name: segmented address of ASCIIZ name 652 ; mode: attribute for file 653 654 ; exit: 655 ; ----- 656 ; BX: file handle or error code ( < 0) 657 658 659 redir_creat: 0 0000981D E8C404 call get_attrib_mode ; AX = mode, CX = attrib 0 00009820 91 xchg ax,cx 0 00009821 83C820 or ax,20h ; set the ARCHIVE bit on create 0 00009824 A3[0000] mov [file_attrib],ax 0 00009827 A3[0000] mov [int2f_stack],ax ; attrib on stack 0 0000982A C706[0000]1711 mov word [int2f_cmd],I2F_CREATE 0 00009830 833E[0000]FF cmp word [current_ldt],-1 ; valid LDT ? 0 00009835 7506 jne redir_creat10 ; no, modify create function 0 00009837 C706[0000]1811 mov word [int2f_cmd],I2F_XCREATE 669 redir_creat10: 0 0000983D EB0F jmp redir_open_create_common 671 672 ; OPEN FILE (OPEN) 673 674 ; +----+----+----+----+----+----+----+----+----+----+ 675 ; | 3D | name | mode | attrib | 676 ; +----+----+----+----+----+----+----+----+----+----+ 677 678 ; entry: 679 ; ------ 680 ; name: segmented address of ASCIIZ name 681 ; mode: open mode 682 ; attrib: file attrib for search (default = 16h) 683 684 ; exit: 685 ; ----- 686 ; BX: file handle or error code ( < 0) 687 688 redir_open: 689 ;---------- 690 ; 0 0000983F E8A204 call get_attrib_mode ; AX = mode, CX = attrib 0 00009842 83E07F and ax,7fh ; remove inheritance bit 0 00009845 A3[0000] mov [int2f_stack],ax 0 00009848 C706[0000]1611 mov word [int2f_cmd],I2F_OPEN 695 redir_open_create_common: 0 0000984E E8[0000] call find_xfn ; get external file handle in DI 0 00009851 BBFCFF mov bx,ED_HANDLE ; assume no handles 0 00009854 7213 jc redir_open20 0 00009856 57 push di 0 00009857 E81000 call redir_openfile ; now do the open 0 0000985A 5F pop di 0 0000985B 720C jc redir_open20 703 ; On Entry: 704 ; AL = IFN 705 ; DI = XFN 706 ; ES:BX -> DHNDL_ 707 ; On Exit: 708 ; PSP fixed up 709 ; 0 0000985D 89FB mov bx,di 0 0000985F E8[0000] call get_xftptr ; ES:DI -> XFN table 0 00009862 7204 jc redir_open10 ; no PSP, skip xfn stuff 0 00009864 01DF add di,bx ; add external file # 0 00009866 AA stosb ; update table entry 0 00009867 C3 ret 716 717 redir_open10: 0 00009868 93 xchg ax,bx ; no PSP, return XFN in BX 719 redir_open20: 0 00009869 C3 ret 721 722 723 redir_openfile: 724 ;-------------- 725 ; On Entry: 726 ; pri_pathname and file_attrib have been set up 727 ; On Exit: 728 ; AL = IFN 729 ; ES:BX = DHNDL_ 730 ; CY set on error, BX = error code 731 ; We should set up COUNT, MODE, UID, PSP, and SHARE 0 0000986A E8[0000] call find_dhndl ; find DHNDL_ 0 0000986D 723E jc redir_openf40 ; return if a problem with this 0 0000986F 50 push ax ; save IFN 0 00009870 06 push es 0 00009871 53 push bx ; save DHNDL_ 737 0 00009872 A1[0000] mov ax,[file_mode] 0 00009875 247F and al,~ DHM_LOCAL 0 00009877 26894702 mov [es:DHNDL_MODE + bx],ax ; save mode in DOSHNDL 0 0000987B 26C747330000 mov word [es:DHNDL_SHARE + bx],0 ; zero share record 742 0 00009881 A1[0000] mov ax,[int2f_cmd] ; either open or create 0 00009884 E87504 call int2f_dhndl ; lets try the command 745 0 00009887 5B pop bx 0 00009888 07 pop es ; recover DHNDL_ 0 00009889 5A pop dx ; recover IFN 0 0000988A 721F jc redir_openf30 ; on error discard the handle 0 0000988C 92 xchg ax,dx ; return AL = IFN 0 0000988D 26C7070100 mov word [es:DHNDL_COUNT + bx],1 ; handle now properly in use 0 00009892 8B0E[0000] mov cx,[file_mode] 0 00009896 F6C580 test ch,DHM_FCB/256 ; is this an FCB open ? 0 00009899 7405 jz redir_openf10 0 0000989B 26804F0380 or byte ptr [es:DHNDL_MODE+1 + bx],DHM_FCB/100h 756 redir_openf10: 0 000098A0 F6C180 test cl,DHM_LOCAL ; is it a "private" file ? 0 000098A3 7405 jz redir_openf20 0 000098A5 26804F0610 or byte ptr [es:DHNDL_WATTR+1 + bx],DHAT_LOCAL/100h 760 redir_openf20: 0 000098AA C3 ret 762 763 redir_openf30: 0 000098AB 93 xchg ax,bx ; returning error in BX 0 000098AC C3 ret 766 767 redir_openf40: 0 000098AD BBFCFF mov bx,ED_HANDLE ; no handles are left 0 000098B0 C3 ret 770 771 ; CLOSE FILE (CLOSE) 772 773 ; +----+----+----+----+ 774 ; | 3E | handle | 775 ; +----+----+----+----+ 776 777 ; entry: 778 ; ------ 779 ; handle: open file handle to be closed 780 781 ; exit: 782 ; ----- 783 ; BX: 0000 or error code ( < 0) 784 785 redir_close: 786 ;------------ 787 ; 0 000098B1 8B7602 mov si,[2 + bp] ; SI -> parameter block 0 000098B4 8B4402 mov ax,[2 + si] ; get external file # 0 000098B7 E8[0000] call get_xftptr ; ES:DI -> xft table 0 000098BA 7208 jc redir_close10 0 000098BC 01C7 add di,ax ; add in XFN 0 000098BE B8FF00 mov ax,0FFh ; get "unused" value for XFT 0 000098C1 268605 xchg al,[es:di] ; release file & get internal # 795 redir_close10: ; we can now do the actual close 0 000098C4 E8[0000] call ifn2dhndl ; ES:BX -> DHNDL_ 0 000098C7 7211 jc redir_close30 ; exit if error occurrs 0 000098C9 268B07 mov ax,[es:DHNDL_COUNT + bx] 0 000098CC B43E mov ah,3eh ; count, AH = 3E 0 000098CE 50 push ax 0 000098CF B80611 mov ax,I2F_CLOSE 0 000098D2 E82704 call int2f_dhndl ; close it 0 000098D5 5B pop bx 0 000098D6 7301 jnc redir_close20 ; errors ? 0 000098D8 93 xchg ax,bx ; recover return code 806 redir_close20: 0 000098D9 C3 ret 808 redir_close30: 0 000098DA BBFAFF mov bx,ED_H_MATCH ; assume invalid IFN 0 000098DD C3 ret 811 812 ; READ FROM FILE (READ) 813 814 ; +----+----+----+----+----+----+----+----+----+----+ 815 ; | 3F | handle | buffer | count | 816 ; +----+----+----+----+----+----+----+----+----+----+ 817 818 ; entry: 819 ; ------ 820 ; handle: open file handle 821 ; buffer: buffer to read into 822 ; count: max. number of bytes to read 823 824 ; exit: 825 ; ----- 826 ; BX: error code ( < 0) 827 828 redir_read: 829 ;---------- 0 000098DE B80811 mov ax,I2F_READ 831 redir_rw_handle: 0 000098E1 8B7602 mov si,[2 + bp] ; SI -> parameter block 0 000098E4 8B4C08 mov cx,[8 + si] ; CX = Count 0 000098E7 1E push ds 0 000098E8 C55404 lds dx,[4 + si] ; DS:DX = DMA address 0 000098EB E80D00 call redir_rw 0 000098EE 1F pop ds 0 000098EF 8B7602 mov si,[2 + bp] ; SI -> parameter block 0 000098F2 894C08 mov [8 + si],cx ; CX = Count 0 000098F5 C3 ret 841 842 ; WRITE TO FILE (WRITE) 843 844 ; +----+----+----+----+----+----+----+----+----+----+ 845 ; | 40 | handle | buffer | count | 846 ; +----+----+----+----+----+----+----+----+----+----+ 847 848 ; entry: 849 ; ------ 850 ; handle: open file handle 851 ; buffer: buffer to be wriiten 852 ; count: max. number of bytes to write 853 854 ; exit: 855 ; ----- 856 ; BX: error code ( < 0) 857 858 redir_write: 859 ;----------- 0 000098F6 B80911 mov ax,I2F_WRITE 0 000098F9 EBE6 jmp redir_rw_handle 862 863 redir_rw: 864 ;-------- 865 ; On Entry: 866 ; AX = command code 867 ; ES:BX = DHNDL_ 868 ; CX = count 869 ; DS:DX = buffer 870 ; On Exit: 871 ; CX = count transferred 872 ; BX = zero or error code 873 ; 0 000098FB 3D0911 cmp ax,I2F_WRITE ; is it a write ? 0 000098FE 7506 jne redir_rw10 0 00009900 26816705BFBF and word [es:DHNDL_WATTR + bx],~ (DHAT_CLEAN+DHAT_TIMEOK) 877 redir_rw10: 0 00009906 36FF36[0000] push word [ss:dma_offset] 0 0000990B 36FF36[0000] push word [ss:dma_segment] 0 00009910 51 push cx 0 00009911 B104 mov cl,4 0 00009913 89D7 mov di,dx ; save dma offset 0 00009915 83E20F and dx,15 ; make offset within para 0 00009918 D3EF shr di,cl ; convert offset to para offset 0 0000991A 8CDE mov si,ds ; add to segment 0 0000991C 01F7 add di,si ; DI:DX -> DMA address 0 0000991E 7708 ja redir_rw15 ; are we within normal TPA ? 0 00009920 47 inc di ; no adjust to offset within 0 00009921 D3E7 shl di,cl ; magic segment FFFF 0 00009923 01FA add dx,di 0 00009925 BFFFFF mov di,0ffffh ; use magic segment 892 redir_rw15: 0 00009928 59 pop cx 0 00009929 368916[0000] mov [ss:dma_offset],dx ; save for xfer 0 0000992E 36893E[0000] mov [ss:dma_segment],di 0 00009933 E8C603 call int2f_dhndl ; try the xfer 0 00009936 368F06[0000] pop word [ss:dma_segment] 0 0000993B 368F06[0000] pop word [ss:dma_offset] 0 00009940 BB0000 mov bx,0 ; assume no error 0 00009943 7316 jnc redir_rw20 0 00009945 93 xchg ax,bx ; return error code 0 00009946 83FBDF cmp bx,ED_LOCKFAIL ; is it a lockfail error ? 0 00009949 7510 jne redir_rw20 ; no, just return it 0 0000994B 36C43E[0000] les di,[ss:current_dhndl] ; compatibility modes should generate 0 00009950 26F745027000 test word [es:DHNDL_MODE + di],DHM_SHAREMSK 0 00009956 7403 jz redir_rw20 ; critical errors fro ED_LOCKFAIL 0 00009958 BBFBFF mov bx,ED_ACCESS ; sharing modes return access denied 908 redir_rw20: 0 0000995B C3 ret 910 911 912 ; DELETE FILE (UNLINK) 913 914 ; +----+----+----+----+----+----+ 915 ; | 41 | name | 916 ; +----+----+----+----+----+----+ 917 918 ; entry: 919 ; ------ 920 ; name: segmented address of ASCIIZ name 921 922 ; exit: 923 ; ----- 924 ; BX: 0000 or error code ( < 0) 925 926 927 redir_unlink: 0 0000995C B81311 mov ax,I2F_DEL ; it's a delete 929 ; mov file_attrib,6 ; only delete files 930 redir_unlink_move_common: 0 0000995F 50 push ax 0 00009960 E88103 call get_attrib_mode ; allow overrides for server calls 0 00009963 58 pop ax 0 00009964 E968FE jmp redir_pathop_common 935 936 ; GET/SET FILE POSITION (LSEEK) 937 938 ; +----+----+----+----+----+----+----+----+----+----+ 939 ; | 42 | handle | offset | method | 940 ; +----+----+----+----+----+----+----+----+----+----+ 941 942 ; On Entry: 943 ; ES:BX = DHDNL_ 944 ; method: 0 = begin, 1 = current, 2 = end of file 945 ; 946 ; On Exit: 947 ; BX = Error Code, offset updated with new value 948 ; 949 950 redir_lseek: 951 ;----------- 0 00009967 89DF mov di,bx ; ES:DI -> DHNDL_ 0 00009969 8B7602 mov si,[2 + bp] ; SI -> parameter block 0 0000996C 8B5404 mov dx,[4 + si] ; get 32-bit file offset 0 0000996F 8B4C06 mov cx,[6 + si] ; into CX,DX 0 00009972 8B4408 mov ax,[8 + si] ; get seek mode 0 00009975 85C0 test ax,ax 0 00009977 7459 jz redir_lseek20 ; seek from beginning 0 00009979 48 dec ax 0 0000997A 7407 jz redir_lseek10 ; seek from current position 0 0000997C 48 dec ax 0 0000997D 746B jz redir_lseek30 ; seek from end 0 0000997F BBF3FF mov bx,ED_DATA ; else invalid seek mode 0 00009982 C3 ret 965 966 redir_lseek10: ; seek mode 1: relative to position 967 ; add dx,es:DHNDL_POSLO[di] ; add position + offset 968 ; adc cx,es:DHNDL_POSHI[di] 0 00009983 26015515 add [es:DHNDL_POSLO + di],dx 0 00009987 26114D17 adc [es:DHNDL_POSHI + di],cx 0 0000998B 2683554700 adc word [es:DHNDL_POSXLO + di],0 0 00009990 2683554900 adc word [es:DHNDL_POSXHI + di],0 0 00009995 F7C10080 test cx,8000h ; negative offset? 0 00009999 740A jz redir_lseek12 0 0000999B 26834547FF add word [es:DHNDL_POSXLO + di],0ffffh; yes, then extend the sign to 64-bit 0 000099A0 26835549FF adc word [es:DHNDL_POSXHI + di],0ffffh 977 redir_lseek12: 0 000099A5 26837D4700 cmp word [es:DHNDL_POSXLO + di],0 0 000099AA 7507 jne redir_lseek15 0 000099AC 26837D4900 cmp word [es:DHNDL_POSXHI + di],0 0 000099B1 7415 je redir_lseek17 982 redir_lseek15: 0 000099B3 26837D47FF cmp word [es:DHNDL_POSXLO + di],0ffffh 0 000099B8 7507 jne redir_lseek16 0 000099BA 26837D49FF cmp word [es:DHNDL_POSXHI + di],0ffffh 0 000099BF 7407 je redir_lseek17 987 redir_lseek16: 0 000099C1 31D2 xor dx,dx 0 000099C3 4A dec dx 0 000099C4 89D1 mov cx,dx 0 000099C6 EB1A jmp redir_lseek90 992 redir_lseek17: 0 000099C8 268B5515 mov dx,[es:DHNDL_POSLO + di] 0 000099CC 268B4D17 mov cx,[es:DHNDL_POSHI + di] 0 000099D0 EB10 jmp redir_lseek90 996 997 redir_lseek20: ; seek mode 0: set absolute position 0 000099D2 26895515 mov [es:DHNDL_POSLO + di],dx ; set new file offset 0 000099D6 26894D17 mov [es:DHNDL_POSHI + di],cx ; SI = error code/0 at this point 0 000099DA 26894547 mov [es:DHNDL_POSXLO + di],ax 0 000099DE 26894549 mov [es:DHNDL_POSXHI + di],ax 1002 ; jmp redir_lseek90 1003 1004 redir_lseek90: 0 000099E2 895404 mov [4 + si],dx ; set 32-bit file offset 0 000099E5 894C06 mov [6 + si],cx ; for return 0 000099E8 93 xchg ax,bx ; error code in BX 0 000099E9 C3 ret 1009 1010 redir_lseek30: ; seek mode 2: relative to end 0 000099EA 268B5D02 mov bx,[es:DHNDL_MODE + di] ; ask MSNET if anyone else can write 0 000099EE 80E370 and bl,DHM_SHAREMSK ; isolate sharing bits 0 000099F1 80FB30 cmp bl,DHM_DENY_READ ; Only DENY_READ and DENY_NONE a 0 000099F4 7210 jb redir_lseek40 ; problem - others might write to 0 000099F6 56 push si ; the file so we must ask the server 1016 ; how long the file is now 0 000099F7 B82111 mov ax,I2F_LSEEK ; CX:DX = position now 0 000099FA E8FF02 call int2f_dhndl ; do a remote seek 0 000099FD 5E pop si ; DX:AX = EOF relative position 0 000099FE 72E2 jc redir_lseek90 ; (unless we have an error) 0 00009A00 92 xchg ax,dx ; AX:DX = new EOF relative position 0 00009A01 91 xchg ax,cx ; and finally get into CX:DX 0 00009A02 31C0 xor ax,ax ; no problems... 1024 ;jmp redir_lseek90 ; MYST-removed,file offset wasn't updated 0 00009A04 EBCC jmp redir_lseek20 ; MYST-added,go and update the new file offset. 1026 redir_lseek40: 0 00009A06 26035511 add dx,[es:DHNDL_SIZELO + di] ; add file size + offset 0 00009A0A 26134D13 adc cx,[es:DHNDL_SIZEHI + di] 0 00009A0E 31C0 xor ax,ax 0 00009A10 EBC0 jmp redir_lseek20 1031 1032 1033 ; GET/SET FILE ATTRIBUTES (CHMOD) 1034 1035 ; +----+----+----+----+----+----+----+----+----+----+ 1036 ; | 43 | name | flag | attrib | 1037 ; +----+----+----+----+----+----+----+----+----+----+ 1038 ; | size | 1039 ; +----+----+----+----+ 1040 1041 ; entry: 1042 ; ------ 1043 ; name: pointer to ASCIIZ file name 1044 ; flag: 0 = get attribute, 1045 ; 1 = set attribute, 1046 ; 2-5 = passwords (ignored) 1047 ; attrib: new attribute if flag = 1 1048 ; password mode if flag = 3 1049 ; 1050 ; exit: 1051 ; ----- 1052 ; BX: 0000 or error code ( < 0) 1053 ; attrib: file's attribute if flag = 0 1054 ; size: file's size 1055 1056 redir_chmod: 1057 ;----------- 1058 ; 0 00009A12 8B5E02 mov bx,[2 + bp] ; BX -> parameter block 0 00009A15 8B4F08 mov cx,[8 + bx] ; get attribs 0 00009A18 8B5F06 mov bx,[6 + bx] ; get access flag 0 00009A1B B80E11 mov ax,I2F_SET_ATTR ; assume it's a set 0 00009A1E 80FB01 cmp bl,1 ; is it a set ? 0 00009A21 740D je redir_chmod10 ; if not then 0 00009A23 B80F11 mov ax,I2F_GET_ATTR ; assume it's a get 0 00009A26 B91600 mov cx,16h ; with everything attribs 0 00009A29 7205 jb redir_chmod10 ; was it ? 0 00009A2B B8FBFF mov ax,ED_ACCESS ; no, return access denied 0 00009A2E EB17 jmp redir_chmod20 ; cause it DR password stuff 1070 redir_chmod10: 0 00009A30 890E[0000] mov [int2f_stack],cx ; attribs on the stack 0 00009A34 E8BE02 call int2f_ldt ; do the Int 2F 0 00009A37 720E jc redir_chmod20 0 00009A39 8B7602 mov si,[2 + bp] ; SI -> parameter block 0 00009A3C 894408 mov [8 + si],ax ; return attribute 0 00009A3F 897C0A mov [10 + si],di 0 00009A42 895C0C mov [12 + si],bx 0 00009A45 31C0 xor ax,ax ; success 1079 redir_chmod20: 0 00009A47 93 xchg ax,bx ; return result in BX 0 00009A48 C3 ret 1082 1083 ; GET DISK PARAMETER BLOCK 1084 1085 ; +----+----+----+----+----+----+----+----+----+----+ 1086 ; | 48 | drive | dpb | adjust | 1087 ; +----+----+----+----+----+----+----+----+----+----+ 1088 1089 ; entry: 1090 ; ------ 1091 ; drive: drive to get information about 1092 1093 ; exit: 1094 ; ----- 1095 ; BX: 0000 or error code ( < 0) 1096 ; dpb: address of DOS DPB (offset/segment) 1097 ; adjust: delwatch adjustment of free space 1098 1099 ; NB. We only fill in the fields required by the Disk Free Space call. 1100 1101 redir_getdpb: 1102 ;------------ 0 00009A49 B80C11 mov ax,I2F_SPACE 0 00009A4C E8A602 call int2f_ldt ; get the info 0 00009A4F 7302 jnc redir_getdpb10 ; if we get an error then make CLMSK=FE 0 00009A51 B0FF mov al,0ffh 1107 redir_getdpb10: 0 00009A53 BE[0000] mov si,offset sec_pathname ; let's re-use this as a temp DPB 0 00009A56 FEC8 dec al ; make cluster mask 0 00009A58 884404 mov [DDSC_CLMSK + si],al ; and stuff into DPB 0 00009A5B 89541F mov [DDSC_FREE + si],dx 0 00009A5E 894C02 mov [DDSC_SECSIZE + si],cx 0 00009A61 43 inc bx ; inc number of clusters 0 00009A62 895C0D mov [DDSC_NCLSTRS + si],bx 0 00009A65 A0[0000] mov al,[err_drv] ; also fill in drive number 0 00009A68 8804 mov [DDSC_UNIT + si],al 0 00009A6A 8B7602 mov si,[2 + bp] ; DI -> parameter block 0 00009A6D C74404[0000] mov word [4 + si],offset sec_pathname 0 00009A72 8C5C06 mov [6 + si],ds ; point to my dummy DPB 0 00009A75 C744080000 mov word ptr [8 + si],0 ; zero adjust value 0 00009A7A BBFF00 mov bx,0ffh ; return 0xFF (ie. bad drive) 0 00009A7D C3 ret 1123 1124 ; FIND FIRST FILE 1125 1126 ; +----+----+----+----+----+----+----+----+----+----+ 1127 ; | 4E | name | ***** | attrib | 1128 ; +----+----+----+----+----+----+----+----+----+----+ 1129 1130 ; entry: 1131 ; ------ 1132 ; name: pointer to ASCIIZ file name 1133 ; attrib: attribute to be used in search 1134 ; 1135 ; exit: 1136 ; ----- 1137 ; BX: 0001 or error code ( < 0) 1138 1139 ; Note: This call returns matching files in 1140 ; the current DMA address and also saves 1141 ; the BDOS state in the there. 1142 ; 1143 ; If there is space for multiple file names we 1144 ; could return as many as will fit into the DTA 1145 ; but it's easier just to return 1 file 1146 ; 1147 1148 redir_first: ; 13-find first matching file 1149 ;---------- 1150 ; ONLY 1 file returned for now..... 1151 ; 0 00009A7E E86302 call get_attrib_mode ; AX = mode, CX = attrib 0 00009A81 B81B11 mov ax,I2F_SFIRST ; srch first, valid LDT 0 00009A84 C43E[0000] les di,[current_ldt] 0 00009A88 83FFFF cmp di,-1 ; valid LDT ? 0 00009A8B 7503 jne redir_first10 0 00009A8D B81911 mov ax,I2F_XSFIRST ; srch first, no valid LDT 1158 redir_first10: 0 00009A90 EB08 jmp srch_buf_common 1160 1161 ; FIND NEXT FILE 1162 1163 ; +----+----+ 1164 ; | 4F | 1165 ; +----+----+ 1166 ; 1167 ; entry: 1168 ; ------ 1169 ; 1170 ; exit: 1171 ; ----- 1172 ; BX: 0000 or error code ( < 0) 1173 1174 ; Note: This call returns matching files in 1175 ; the current DMA address and also saves 1176 ; the BDOS state in the there. 1177 1178 redir_next: ; 14-find next matching file 1179 ;--------- 1180 ; ONLY 1 file returned for now..... 1181 ; 0 00009A92 16 push ss 0 00009A93 07 pop es 0 00009A94 BF[0000] mov di,offset srch_buf ; point ES:DI -> search buffer 0 00009A97 B81C11 mov ax,I2F_SNEXT 1186 srch_buf_common: 0 00009A9A FF36[0000] push word [dma_offset] 0 00009A9E FF36[0000] push word [dma_segment] 0 00009AA2 C706[0000][0000] mov word [dma_offset],offset srch_buf 0 00009AA8 8C1E[0000] mov [dma_segment],ds 0 00009AAC E85202 call int2f_op 1192 0 00009AAF 8F06[0000] pop word [dma_segment] 0 00009AB3 8F06[0000] pop word [dma_offset] 0 00009AB7 7205 jc srch_buf_common10 0 00009AB9 E80400 call redir_save_srch_state ; if no error save state 0 00009ABC 31C0 xor ax,ax ; return AX = 1 file found 1198 srch_buf_common10: 0 00009ABE 93 xchg ax,bx ; return code in BX 0 00009ABF C3 ret 1201 1202 1203 redir_save_srch_state: 1204 ; On entry DS=PCMODE 0 00009AC0 C43E[0000] les di,[dma_offset] ; ES:DI -> search state in DMA address 1206 0 00009AC4 BE[0000] mov si,offset srch_buf 0 00009AC7 B91500 mov cx,21 ; save 1st 21 bytes 0 00009ACA F3A4 rep movsb 1210 0 00009ACC 56 push si ; save name/ext 0 00009ACD 83C60B add si,11 ; skip to name/ext 0 00009AD0 A4 movsb ; copy the attribute 0 00009AD1 83C60A add si,10 ; skip reserved bytes 0 00009AD4 A5 movsw ; copy the time 0 00009AD5 A5 movsw ; copy the date 0 00009AD6 83C602 add si,2 ; skip starting cluster 0 00009AD9 A5 movsw ; copy the file size 0 00009ADA A5 movsw 0 00009ADB 5B pop bx ; recover name 0 00009ADC E9[0000] jmp unparse ; unparse the name 1222 1223 ; Restore DOS search area from user DTA 1224 ; 1225 redir_restore_srch_state: 1226 ;------------------------ 1227 ; On Entry: 1228 ; DS = SYSDAT 1229 ; On Exit: 1230 ; AL = 1st byte of srch buf 1231 ; DS preserved 1232 ; 0 00009ADF 16 push ss 0 00009AE0 07 pop es 0 00009AE1 BF[0000] mov di,offset srch_buf ; ES:DI -> internal state 0 00009AE4 1E push ds 0 00009AE5 36C536[0000] lds si,[ss:dma_offset] 0 00009AEA AC lodsb ; DS:SI -> search state in DMA address 0 00009AEB AA stosb 0 00009AEC B91400 mov cx,20 ; copy 1st 21 bytes 0 00009AEF F3A4 rep movsb 0 00009AF1 1F pop ds 0 00009AF2 C3 ret 1244 1245 ; COMMIT FILE (COMMIT) 1246 1247 ; +----+----+----+----+ 1248 ; | 50 | handle | 1249 ; +----+----+----+----+ 1250 1251 ; entry: 1252 ; ------ 1253 ; handle: open file handle to be flushed 1254 1255 ; exit: 1256 ; ----- 1257 ; BX: 0000 or error code ( < 0) 1258 1259 redir_commit: 0 00009AF3 26F747020300 test word [es:DHNDL_MODE + bx],DHM_WO+DHM_RW 0 00009AF9 7408 jz redir_commit10 ; we don't need to commit it 0 00009AFB B80711 mov ax,I2F_COMMIT 0 00009AFE E8FB01 call int2f_dhndl ; commit this file 0 00009B01 7202 jc redir_commit20 1265 redir_commit10: 0 00009B03 31C0 xor ax,ax ; success 1267 redir_commit20: 0 00009B05 93 xchg ax,bx ; return result in BX 0 00009B06 C3 ret 1270 1271 1272 ; CREATE NEW FILE 1273 1274 ; +----+----+----+----+----+----+----+----+ 1275 ; | 51 | name | mode | 1276 ; +----+----+----+----+----+----+----+----+ 1277 1278 ; entry: 1279 ; ------ 1280 ; name: segmented address of ASCIIZ name 1281 ; mode: attribute for file 1282 1283 ; exit: 1284 ; ----- 1285 ; BX: file handle or error code ( < 0) 1286 1287 ; Note: The function is identical to CREATE FILE 1288 ; with the exception that an error is returned 1289 ; if the specified file already exists. 1290 1291 redir_mknew: 0 00009B07 E8DA01 call get_attrib_mode ; AX = mode, CX = attrib 0 00009B0A 91 xchg ax,cx 0 00009B0B 0D2001 or ax,120h ; set ARCHIVE + MKNEW bits 0 00009B0E A3[0000] mov [file_attrib],ax 0 00009B11 A3[0000] mov [int2f_stack],ax 0 00009B14 C706[0000]1711 mov word [int2f_cmd],I2F_CREATE 0 00009B1A C706[0000]0200 mov word [file_mode],DHM_RW ; Open Compatibility mode, Read/Write 0 00009B20 E92BFD jmp redir_open_create_common 1300 1301 ; LOCK/UNLOCK FILE DATA (LOCK/UNLOCK) 1302 1303 ; +----+----+----+----+----+----+----+----+ 1304 ; | 52 | handle | offset | 1305 ; +----+----+----+----+----+----+----+----+ 1306 ; | length | lock | 1307 ; +----+----+----+----+----+----+ 1308 1309 ; entry: 1310 ; ------ 1311 ; handle: open file handle 1312 ; offset: long integer offset 1313 ; length: long integer byte count 1314 ; lock: 0 = lock, 1 = unlock 1315 1316 ; exit: 1317 ; ----- 1318 ; BX: byte count or error code ( < 0) 1319 1320 redir_lock: 1321 ; Lock uses I2F_LOCK, with CX,DX,SI as per INT 21, DI on stack 1322 ; Unlock uses I2F_UNLOCK with same. 0 00009B23 8B5E02 mov bx,[2 + bp] ; BX -> parameter block 0 00009B26 55 push bp 0 00009B27 8D6F04 lea bp,[4 + bx] ; BP -> parameter block 0 00009B2A 89EA mov dx,bp ; as does DX 0 00009B2C B80A11 mov ax,I2F_LOCK 0 00009B2F 8A5F0C mov bl,byte ptr [12 + bx] 0 00009B32 B75C mov bh,5Ch ; lock/unlock in BX 0 00009B34 E8C501 call int2f_dhndl ; try the operation 0 00009B37 5D pop bp 0 00009B38 7202 jc redir_lock20 0 00009B3A 31C0 xor ax,ax ; success 1334 redir_lock20: 0 00009B3C 93 xchg ax,bx ; return result in BX 0 00009B3D C3 ret 1337 1338 1339 ; EXPAND FILE 1340 1341 ; +----+----+----+----+----+----+----+----+----+----+ 1342 ; | 55 | old name | new name | 1343 ; +----+----+----+----+----+----+----+----+----+----+ 1344 1345 ; entry: 1346 ; ------ 1347 ; old name: segmented address of ASCIIZ name 1348 ; new name: segmented address of ASCIIZ name 1349 1350 ; exit: 1351 ; ----- 1352 ; BX: 0000 or error code ( < 0) 1353 1354 ; If we got here pri_pathname already contains expanded name - just copy it 1355 ; back to the users buffer. 1356 1357 redir_expand: 1358 ;------------ 0 00009B3E 8B7602 mov si,[2 + bp] ; SI -> parameter block 0 00009B41 C47C0A les di,[10 + si] ; ES:DI -> user supplied name 0 00009B44 BE[0000] mov si,offset pri_pathname 0 00009B47 E8[0000] call copy_asciiz 0 00009B4A 31DB xor bx,bx ; no errors 0 00009B4C C3 ret 1365 1366 ; RENAME FILE 1367 1368 ; +----+----+----+----+----+----+----+----+----+----+ 1369 ; | 56 | old name | new name | 1370 ; +----+----+----+----+----+----+----+----+----+----+ 1371 1372 ; entry: 1373 ; ------ 1374 ; old name: segmented address of ASCIIZ name 1375 ; new name: segmented address of ASCIIZ name 1376 1377 ; exit: 1378 ; ----- 1379 ; BX: 0000 or error code ( < 0) 1380 1381 ; Note: R/O files can be renamed. 1382 ; --- 1383 1384 redir_move: 0 00009B4D B81111 mov ax,I2F_REN ; it's a rename 0 00009B50 E90CFE jmp redir_unlink_move_common 1387 1388 ; GET/SET FILE DATE/TIME 1389 1390 ; +----+----+----+----+----+----+----+----+----+----+ 1391 ; | 57 | handle | mode | date | time | 1392 ; +----+----+----+----+----+----+----+----+----+----+ 1393 1394 ; entry: 1395 ; ------ 1396 ; handle: open file handle 1397 ; mode: 0 = get date/time, 1 = set date/time 1398 ; date: date as in directory FCB 1399 ; time: time as in directory FCB 1400 1401 ; exit: 1402 ; ----- 1403 ; BX: 0000 or error code ( < 0) 1404 ; date: date of last modification if mode = 0 1405 ; time: date of last modification if mode = 0 1406 1407 redir_dattim: 1408 ;------------ 0 00009B53 8B7602 mov si,[2 + bp] ; DS:SI -> param block 0 00009B56 837C0401 cmp word ptr [4 + si],1 ; is it set ? 0 00009B5A 772F ja redir_dattim30 ; if illegal say so 0 00009B5C 7410 je redir_dattim10 0 00009B5E 268B470F mov ax,[es:DHNDL_DATE + bx] ; we need to copy the file date 0 00009B62 894406 mov word ptr [6 + si],ax ; into the parameter block 0 00009B65 268B470D mov ax,[es:DHNDL_TIME + bx] 0 00009B69 894408 mov word ptr [8 + si],ax ; and the time 0 00009B6C EB19 jmp redir_dattim20 1418 redir_dattim10: 0 00009B6E 8B4406 mov ax,word ptr [6 + si] ; copy the date we are given 0 00009B71 2689470F mov [es:DHNDL_DATE + bx],ax ; into the DOSHNDL 0 00009B75 8B4408 mov ax,word ptr [8 + si] ; and the time 0 00009B78 2689470D mov [es:DHNDL_TIME + bx],ax 0 00009B7C 26814F050040 or word [es:DHNDL_WATTR + bx],DHAT_TIMEOK 0 00009B82 26836705BF and word [es:DHNDL_WATTR + bx],~ DHAT_CLEAN 1425 redir_dattim20: 0 00009B87 31DB xor bx,bx ; all went OK 0 00009B89 EB03 jmp redir_dattim40 1428 redir_dattim30: 0 00009B8B BBFFFF mov bx,ED_FUNCTION ; bad function number 1430 redir_dattim40: 0 00009B8E C3 ret 1432 1433 Public redir_build_path 1434 1435 ; AH contains state of path processing, and is normally zero 1436 1437 BP_DOT equ 1 ; we have had a DOT end are processing the .EXT 1438 BP_WILD equ 2 ; we have encountered a wild card 1439 BP_BSLASH equ 4 ; the last character was a BSLASH 1440 1441 ; May be called with or without MXDisk 1442 1443 redir_build_path: 1444 ;---------------- 1445 ; On Entry: 1446 ; DS:SI -> source name 1447 ; ES:DI -> destination name (in PCMODE data segment) 1448 ; current_ldt -> LDT_ for specified drive 1449 ; On Exit: 1450 ; CY clear if we could build the path 1451 ; 1452 ; firstly we discard any drive portion 0 00009B8F AD lodsw ; get 1st two characters 0 00009B90 80FC3A cmp ah,':' ; is a drive specified ? 0 00009B93 7501 jne redir_bp10 ; discard "d:" if so 0 00009B95 AD lodsw 1457 redir_bp10: 1458 ; Is it a "\\server\sharename\subdir\filename.ext" format ? 0 00009B96 E8[0000] call check_dslash ; if it is \\. 0 00009B99 741F je redir_bp20 ; then just copy the lot 1461 ; it's a normal "A:\subdir\filename.ext" pathname format 0 00009B9B 4E dec si ; we have swallowed the 1st two 0 00009B9C 4E dec si ; chars - now we change our mind 0 00009B9D 1E push ds 0 00009B9E 56 push si 0 00009B9F 26C536[0000] lds si,[es:current_ldt] 0 00009BA4 8B4C4F mov cx,[LDT_ROOTLEN + si] ; copy the root portion of the name 0 00009BA7 F3A4 rep movsb ; copy the server stub name 0 00009BA9 89FA mov dx,di ; ES:DX -> root position 0 00009BAB E8[0000] call check_slash ; do we start from the root ? 0 00009BAE 7406 je redir_bp11 ; yes, then that's all 0 00009BB0 E8[0000] call copy_asciiz ; no, copy the rest of the path 0 00009BB3 E80A01 call redir_bp_append_slash ; append '\' for our path processing 1474 redir_bp11: 0 00009BB6 5E pop si 0 00009BB7 1F pop ds 0 00009BB8 EB5B jmp redir_bp_next_level ; continue processing given path 1478 1479 redir_bp20: 1480 ; It is a "\\server\sharename\subdir\filename.ext" format 0 00009BBA AB stosw ; copy the "\\" 0 00009BBB 31C0 xor ax,ax ; clear "flags" in AH 1483 redir_bp21: 0 00009BBD AC lodsb ; work along the name 0 00009BBE 84C0 test al,al ; unexpected end of name ? 0 00009BC0 744F jz redir_bp_exit20 ; go with what we've got.... 0 00009BC2 E8[0000] call check_slash ; have we found the root '\' ? 0 00009BC5 740F je redir_bp23 1489 %ifdef KANJI 0 00009BC7 E8[0000] call dbcs_lead ; is it the 1st of a kanji pair 0 00009BCA 7504 jne redir_bp22 ; no, onto next char 0 00009BCC AA stosb ; copy the 1st character 0 00009BCD A4 movsb ; copy 2nd byte of KANJI pair 0 00009BCE EBED jmp redir_bp21 ; now we can move onto next char 1495 redir_bp22: 1496 %endif 0 00009BD0 E8[0000] call toupper ; upper case the character 0 00009BD3 AA stosb ; copy the character 0 00009BD4 EBE7 jmp redir_bp21 ; go and do another one 1500 1501 redir_bp23: 0 00009BD6 89FA mov dx,di ; bodge root to the top 1503 ; mov al,'\' 0 00009BD8 AA stosb ; put in a '\' 0 00009BD9 EB3A jmp redir_bp_next_level ; yes, this is the new "root" 1506 1507 ; We have reached the terminating NUL 1508 redir_bp_exit: 0 00009BDB F6C402 test ah,BP_WILD ; did we get any wildcards ? 0 00009BDE 741E je redir_bp_exit10 0 00009BE0 8B7602 mov si,[2 + bp] ; SS:SI -> parameter block 0 00009BE3 368A04 mov al,[ss:si] ; fdos code number 0 00009BE6 3C4E cmp al,MS_X_FIRST ; search first ? 0 00009BE8 7414 je redir_bp_exit10 0 00009BEA 3C55 cmp al,FD_EXPAND ; expand pathname 0 00009BEC 7410 je redir_bp_exit10 0 00009BEE 36833E[0000]00 cmp word [ss:remote_call],0 ; should we wildcard REN/DEL ? 0 00009BF4 7466 je redir_bp_ED_PATH ; reject as not allowed here 0 00009BF6 3C56 cmp al,MS_X_RENAME ; rename ? 0 00009BF8 7404 je redir_bp_exit10 0 00009BFA 3C41 cmp al,MS_X_UNLINK ; delete ? 0 00009BFC 755E jne redir_bp_ED_PATH ; reject as not allowed here 1523 redir_bp_exit10: 0 00009BFE 30C0 xor al,al ; make sure our string is zero 0 00009C00 AA stosb ; terminated 0 00009C01 E8BC00 call redir_bp_append_slash ; append a trailing '\' if we don't 0 00009C04 4F dec di ; have one so we can remove it 0 00009C05 39D7 cmp di,dx ; are we talking about the root ? 0 00009C07 7508 jne redir_bp_exit20 0 00009C09 26807DFF3A cmp byte ptr [es:di-1],':' 0 00009C0E 7501 jne redir_bp_exit20 ; if we have a trailing ':' allow 0 00009C10 47 inc di ; a '\' at the root 1533 redir_bp_exit20: 0 00009C11 30C0 xor al,al ; KANJI aware way of removing trailing 0 00009C13 AA stosb ; '\' from the path.... 1536 ; clc 0 00009C14 C3 ret 1538 1539 1540 redir_bp_next_level: 1541 ; DS:SI -> source pathname, ES:DI -> destination pathname, ES:DX -> root 1542 ; AH = current status 0 00009C15 B90800 mov cx,8 ; expansion count ready 0 00009C18 31C0 xor ax,ax 1545 redir_bp_next_char: 0 00009C1A AC lodsb 0 00009C1B 84C0 test al,al ; end of the line ? 0 00009C1D 74BC jz redir_bp_exit ; do the exit 1549 1550 ; Is it a '\' ? 1551 redir_bp40: 0 00009C1F E8[0000] call check_slash ; was it a seperator ? 0 00009C22 750A jne redir_bp50 0 00009C24 F6C402 test ah,BP_WILD ; have we encountered wildcards ? 0 00009C27 7533 jnz redir_bp_ED_PATH ; reject as not allowed here 0 00009C29 B05C mov al,'\' ; make sure it's a BSLASH 0 00009C2B AA stosb 0 00009C2C EBE7 jmp redir_bp_next_level ; start at a new level 1559 1560 ; Is it a '.' ? 1561 redir_bp50: 0 00009C2E 3C2E cmp al,'.' ; seperator ? 0 00009C30 752F jne redir_bp60 0 00009C32 AC lodsb ; get next letter 0 00009C33 84C0 test al,al ; is it trailing '.' ? 0 00009C35 74A4 je redir_bp_exit ; then exit now 0 00009C37 83F908 cmp cx,8 ; check for '.' and '..' 0 00009C3A 7412 je redir_bp52 ; if at start of field 1569 redir_bp51: ; othewise it's a ".EXT" 0 00009C3C BBFEFF mov bx,ED_FILE ; assume we have a problem 0 00009C3F F6C401 test ah,BP_DOT ; have we had an extention before ? 0 00009C42 751B jnz redir_bp_err ; we've got a problem 0 00009C44 4E dec si ; rewind a character 0 00009C45 B82E01 mov ax,'.'+256*BP_DOT ; so we are back to the '.' 0 00009C48 AA stosb ; store the '.' in destination 0 00009C49 B90300 mov cx,3 ; expand the extention 0 00009C4C EBCC jmp redir_bp_next_char 1578 redir_bp52: ; It might be a "." or ".." 0 00009C4E E8[0000] call check_slash ; is it '.\' 0 00009C51 74C7 je redir_bp_next_char ; discard them both 0 00009C53 3C2E cmp al,'.' ; is it '..' ? 0 00009C55 75E5 jne redir_bp51 ; no, must be an extention after all 0 00009C57 E83200 call redir_bp_ddot ; rewind a level 0 00009C5A 73B9 jnc redir_bp_next_level ; onto next level 1585 redir_bp_ED_PATH: 1586 ; set CY flag to indicate error then return 0 00009C5C BBFDFF mov bx,ED_PATH ; return "invalid path" error 1588 redir_bp_err: 0 00009C5F F9 stc 0 00009C60 C3 ret 1591 1592 ; Is it a '*' ? 1593 redir_bp60: 0 00009C61 E8[0000] call check_delim ; is it a delimiter ? 0 00009C64 74F6 jz redir_bp_ED_PATH ; thats illegal at this point 0 00009C66 3C2A cmp al,'*' ; wildcards ? 0 00009C68 7504 jne redir_bp70 0 00009C6A B03F mov al,'?' 0 00009C6C F3AA rep stosb ; expand it 1600 ; or ah,BP_WILD ; remember wild-card encountered 1601 ; jmp redir_bp_next_char ; check for wildcards 1602 ; 1603 ; ; we can just fall through 1604 ; 1605 redir_bp70: 0 00009C6E 3C3F cmp al,'?' ; wild card is possibly OK 0 00009C70 7503 jne redir_bp80 0 00009C72 80CC02 or ah,BP_WILD ; remember wild-card encountered 1609 redir_bp80: 1610 ; Normal Character 1611 ; AL contains a normal character for us to process. 1612 ; Uppercase the character, look out for KANJI etc 0 00009C75 E3A3 jcxz redir_bp_next_char ; discard if no space is left 0 00009C77 49 dec cx ; one less to expand 1615 %ifdef KANJI 0 00009C78 E8[0000] call dbcs_lead ; is it the 1st of a kanji pair 0 00009C7B 7509 jne redir_bp90 0 00009C7D 46 inc si ; skip 2nd byte 0 00009C7E E39A jcxz redir_bp_next_char ; discard if no room for kanji char 0 00009C80 49 dec cx ; one less to expand 0 00009C81 AA stosb ; store 1st byte of kanji character 0 00009C82 4E dec si ; point at 2nd byte again 0 00009C83 A4 movsb ; copy 2nd byte of kanji character 0 00009C84 EB94 jmp redir_bp_next_char 1625 redir_bp90: 1626 %endif 0 00009C86 E8[0000] call toupper ; make it upper case 0 00009C89 AA stosb ; plant the character 0 00009C8A EB8E jmp redir_bp_next_char 1630 1631 1632 redir_bp_ddot: 1633 ; We have encountered a '..' in a pathname, so rewind up a level 1634 ; On Entry: 1635 ; DS:SI -> source position, ES:DI -> destination position 1636 ; ES:DX -> root position, AL = Character 1637 ; On Exit: 1638 ; ES:DI -> start of field one level up, unless we get an error when CY set. 0 00009C8C AC lodsb ; look at char after '..' 0 00009C8D E8[0000] call check_slash ; is it '..\' 0 00009C90 7405 je redir_bp_ddot10 0 00009C92 84C0 test al,al ; is it a trailing '..' 0 00009C94 75C6 jnz redir_bp_ED_PATH ; no, anything else is bad... 0 00009C96 4E dec si ; trailing '..', rewind to NUL 1645 redir_bp_ddot10: 0 00009C97 4F dec di ; move back to last '\' 0 00009C98 39D7 cmp di,dx ; are we at the root anyway ? 0 00009C9A 7EC0 jle redir_bp_ED_PATH ; then don't discard any 1649 ; We now start at ES:DX and work along till ES:DI -> char after last '\' 0 00009C9C 1E push ds 0 00009C9D 56 push si 0 00009C9E 06 push es 0 00009C9F 1F pop ds 0 00009CA0 89D6 mov si,dx ; DS:SI -> char after root 0 00009CA2 89D1 mov cx,dx ; last '\' position in CX 1656 redir_bp_ddot20: 0 00009CA4 AC lodsb 0 00009CA5 39FE cmp si,di ; end of the line yet ? 0 00009CA7 7311 jae redir_bp_ddot30 ; yes, stop now 1660 %ifdef KANJI 0 00009CA9 E8[0000] call dbcs_lead ; is it 1st of a kanji pair ? 0 00009CAC 7503 jne redir_bp_ddot25 0 00009CAE AC lodsb ; skip the 2nd too 0 00009CAF EBF3 jmp redir_bp_ddot20 ; then go on to next char 1665 redir_bp_ddot25: 1666 %endif 0 00009CB1 E8[0000] call check_slash ; is it a '\' 0 00009CB4 75EE jne redir_bp_ddot20 ; no, do next 0 00009CB6 89F1 mov cx,si ; save position after the '\' 0 00009CB8 EBEA jmp redir_bp_ddot20 1671 redir_bp_ddot30: 0 00009CBA 89CF mov di,cx ; last '\' was here.. 0 00009CBC 5E pop si 0 00009CBD 1F pop ds 0 00009CBE F8 clc ; no errors 0 00009CBF C3 ret 1677 1678 redir_bp_append_slash: 1679 ; On Entry: 1680 ; ES:DX -> ASCIIZ string to append a '\' to 1681 ; On Exit: 1682 ; ES:DI -> terminating NUL 1683 ; All but AX preserved 1684 ; 0 00009CC0 31C0 xor ax,ax ; AH = 0, initially no previous char 0 00009CC2 89D7 mov di,dx ; start processing from here 1687 redir_bp_append_slash10: 0 00009CC4 88C4 mov ah,al ; save previous char in AH 0 00009CC6 268A05 mov al,[es:di] ; get a character 0 00009CC9 47 inc di ; point to next 0 00009CCA 84C0 test al,al ; is it NUL ? 1692 %ifdef KANJI 0 00009CCC 7408 je redir_bp_append_slash20 0 00009CCE E8[0000] call dbcs_lead ; is it 1st of a kanji pair ? 0 00009CD1 75F1 jne redir_bp_append_slash10 0 00009CD3 47 inc di ; skip the 2nd too 0 00009CD4 EBEE jmp redir_bp_append_slash10 ; (it might be '\') 1698 redir_bp_append_slash20: 1699 %else 1700 jnz redir_bp_append_slash10 1701 %endif 0 00009CD6 88E0 mov al,ah ; get previous char 0 00009CD8 E8[0000] call check_slash ; did we have a '\' ? 0 00009CDB 7405 je redir_bp_append_slash30 0 00009CDD 4F dec di ; ES:DI -> existing NUL 0 00009CDE B85C00 mov ax,'\' 0 00009CE1 AB stosw ; new terminating '\' 1708 redir_bp_append_slash30: 0 00009CE2 4F dec di ; ES:DI -> NUL 0 00009CE3 C3 ret 1711 1712 1713 1714 get_attrib_mode: 1715 ;--------------- 1716 ; On Entry: 1717 ; SS:2[BP] -> param block 1718 ; On Exit: 1719 ; AX = file mode 1720 ; CX = file attributes 1721 ; 0 00009CE4 8B7602 mov si,[2 + bp] ; SI -> parameter block 0 00009CE7 8B4406 mov ax,[6 + si] ; get mode 0 00009CEA 8B4C08 mov cx,[8 + si] ; get attribs 0 00009CED A3[0000] mov [file_mode],ax ; save open mode 0 00009CF0 890E[0000] mov [file_attrib],cx ; save file attribute 0 00009CF4 C3 ret 1728 1729 int2f_ldt: 1730 ;--------- 1731 ; On Entry: 1732 ; AX = Int2F command 1733 ; On Exit: 1734 ; CY clear, AX returned unchanged 1735 ; CY set, AX = Our Negative Error Code 1736 ; 0 00009CF5 36C43E[0000] les di,[ss:current_ldt] 0 00009CFA EB05 jmp int2f_op 1739 1740 int2f_dhndl: 1741 ;---------- 1742 ; On Entry: 1743 ; AX = Int2F command 1744 ; On Exit: 1745 ; CY clear, AX returned unchanged 1746 ; CY set, AX = Our Negative Error Code 1747 ; 0 00009CFC 36C43E[0000] les di,[ss:current_dhndl] 1749 int2f_op: 0 00009D01 1E push ds 0 00009D02 16 push ss 0 00009D03 1F pop ds 0 00009D04 FF36[0000] push word [int2f_stack] ; put word on stack 0 00009D08 CD2F int 2fh ; get the info 0 00009D0A 8F06[0000] pop word [int2f_stack] ; clean up the stack 0 00009D0E 1F pop ds 0 00009D0F 7302 jnc int2f_op10 0 00009D11 F7D8 neg ax ; AX = we keep error codes negative 1759 ; stc ; we have a problem 1760 int2f_op10: 0 00009D13 C3 ret 1762 BDOS_CODE ends 1763 1764 end === Trace listing source: drdos/bin/dirs.lst 1 ;title 'DIRS - dos directory support' 2 ; File : $DIRS.ASM$ 3 ; 4 ; Description : 5 ; 6 ; Original Author : DIGITAL RESEARCH 7 ; 8 ; Last Edited By : $CALDERA$ 9 ; 10 ;-----------------------------------------------------------------------; 11 ; Copyright Work of Caldera, Inc. All Rights Reserved. 12 ; 13 ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, 14 ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. 15 ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES 16 ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF 17 ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO 18 ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE 19 ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE 20 ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, 21 ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, 22 ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, 23 ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF 24 ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT 25 ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND 26 ; CIVIL LIABILITY. 27 ;-----------------------------------------------------------------------; 28 ; 29 ; *** Current Edit History *** 30 ; *** End of Current Edit History *** 31 ; 32 ; $Log$ 33 ; DIRS.A86 1.13 94/12/01 13:16:24 34 ; changed error code if directory entry cannot be allocated; 35 ; DIRS.A86 1.12 93/08/27 18:49:04 36 ; hash code fixup on previously unused entries resets hash count 37 ; pcformat bug where an extra (zero-length) command.com was left on disk 38 ; ENDLOG 39 ; 40 ; Date Who Modification 41 ; --------- --- --------------------------------------- 42 ; 19 Aug 91 Initial version created for VLADIVAR 43 44 group PCMCODE BDOS_CODE 45 group PCMDATA BDOS_DATA PCMODE_DATA FIXED_DOS_DATA 46 47 ASSUME DS:PCMDATA 48 49 [list -] 54 55 === Switch to base=00C180h -> "PCMODE_DATA" 56 section PCMODE_DATA public align=2 class=DATA 57 PCMODE_DATA ends 58 === Switch to base=00C180h -> "FIXED_DOS_DATA" 59 section FIXED_DOS_DATA public align=2 class=DATA 60 %ifdef DELWATCH 61 extrn fdos_stub:dword ; for calling delwatch TSR 62 %endif 63 FIXED_DOS_DATA ends 64 === Switch to base=00C180h -> "BDOS_DATA" 65 section BDOS_DATA public align=2 class=DATA 66 extrn adrive:byte 67 EXTRN clsize:WORD 68 extrn diradd:word 69 extrn dirinroot:word 70 EXTRN dirperclu:WORD 71 EXTRN dosfat:WORD 72 extrn hashroot:dword 73 extrn hashmax:word 74 EXTRN info_fcb:BYTE 75 extrn lastcl:word 76 extrn blastcl:word 77 extrn psecsiz:word 78 extrn fsroot:dword 79 80 0 0000195E 00000000 hash dw 2 dup (0) ; hash code work area 82 83 ; The dirbcb says what is in the local dirbuf 84 0 00001962 FF dirbcb db 0ffh ; drive of dirbuf entry 0 00001963 00000000 dirbcb_cl dw 0,0 ; cluster of dirbuf entry 0 00001967 0000 dirbcb_dcnt dw 0 ; directory index of dirbuf entry 0 00001969 00000000 dirbcb_block dw 2 dup (0) ; block of dirbuf entry 0 0000196D 0000 dirbcb_offset dw 0 ; byte offset in block of dirbuf entry 90 91 92 public dirbuf 0 0000196F 000000000000000000 dirbuf db 32 dup (0) ; local directory buffer 0 00001978 000000000000000000 0 00001981 000000000000000000 0 0000198A 0000000000 94 95 public dirp 0 0000198F 0000 dirp dw 0 ; directory entry pointer 97 98 public dcnt 0 00001991 0000 dcnt dw 0 ; directory index count 100 101 public finddfcb_mask 0 00001993 0008 finddfcb_mask dw 0800h ; hi byte = reject DA_VOLUME attribs 103 ; lo byte = accept non-0 start clusters 104 ; 00FF = include labels, but not 105 ; pending deletes 106 ; 0000 = include everything 107 public chdblk 0 00001995 00000000 chdblk dw 0,0 ; current cluster # of directory 109 0 00001999 00000000 rd_pcdir_cl dw 0,0 ; current cluster in rd_pcdir 0 0000199D 0000 rd_pcdir_rel dw 0 ; relative cluster in chain 0 0000199F 0000 rd_pcdir_last dw 0 ; last relative position 0 000019A1 00000000 find_hcb_cl dw 0,0 ; current cluster in find_hcb 114 BDOS_DATA ends 115 === Switch to base=000000h -> "BDOS_CODE" 116 section BDOS_CODE public align=1 class=CODE 117 extrn alloc_cluster:NEAR 118 extrn clus2sec:near 119 extrn hdsblk:near ; get current directory block 120 extrn fdos_error:NEAR 121 extrn fixfat:NEAR 122 extrn getnblk:NEAR 123 extrn locate_buffer:near 124 extrn update_dir:NEAR 125 extrn update_fat:NEAR 126 extrn zeroblk:near 127 extrn div32:near 128 extrn output_msg:near 129 extrn output_hex:near 130 131 public allocdir 132 public discard_dirbuf 133 public finddfcb 134 public finddfcbf 135 public fill_dirbuf 136 public flush_dirbuf 137 public getdir 138 public hshdscrd 139 public mkhsh 140 public setenddir 141 public rd_pcdir 142 143 144 fill_dirbuf: ;get 32 byte directory entry 145 ;---------- 146 ; On Entry: 147 ; DX:AX = cluster to read (0=root) 148 ; BX = dir within cluster 149 ; On Exit: 150 ; DI -> dirbuf entry 151 0 00009D14 E8D800 call discard_dirbuf ; invalidate block in case of error 0 00009D17 A3[0500] mov [dirbcb_cl],ax ; remember which cluster 0 00009D1A 8916[0700] mov [dirbcb_cl+2],dx 0 00009D1E 891E[0900] mov [dirbcb_dcnt],bx ; and dir entry we want 0 00009D22 85C0 test ax,ax ; are we in the root ? 157 ; jz fill_dirbuf10 0 00009D24 7512 jnz fill_dirbuf05 0 00009D26 85D2 test dx,dx 0 00009D28 750E jnz fill_dirbuf05 0 00009D2A 833E[0000]00 cmp word [dirinroot],0 ; is this a FAT32 file system? 0 00009D2F 751B jne fill_dirbuf10 ; no, proceed with FAT16/12 routine 0 00009D31 A1[0000] mov ax,word ptr [fsroot] ; low word of root dir cluster 0 00009D34 8B16[0200] mov dx,word ptr [fsroot+2] 165 fill_dirbuf05: 166 ; mov cl,FCBSHF 167 ; shl bx,cl ; BX = byte offset in cluster 0 00009D38 B90500 mov cx,FCBSHF 0 00009D3B 50 push ax 0 00009D3C 31C0 xor ax,ax 171 fill_dirbuf07: 0 00009D3E D1E3 shl bx,1 ; BX = byte offset in cluster 0 00009D40 D1D0 rcl ax,1 0 00009D42 E2FA loop fill_dirbuf07 0 00009D44 89C1 mov cx,ax 0 00009D46 58 pop ax 0 00009D47 E8[0000] call clus2sec ; DX:AX -> sector 0 00009D4A EB13 jmp fill_dirbuf20 ; BX = offset in sector 179 fill_dirbuf10: 0 00009D4C B82000 mov ax,FCBLEN 0 00009D4F F7E3 mul bx ; DX:AX = byte offset 0 00009D51 F736[0000] div word [psecsiz] ; AX = sector offset, DX = byte offset 0 00009D55 89D3 mov bx,dx ; BX = byte offset in sector 0 00009D57 31D2 xor dx,dx 0 00009D59 0306[0000] add ax,[diradd] ; add in start of root dir 0 00009D5D 11D2 adc dx,dx 187 fill_dirbuf20: 0 00009D5F A3[0B00] mov [dirbcb_block],ax ; we want this sector 0 00009D62 8916[0D00] mov [dirbcb_block+2],dx 0 00009D66 891E[0F00] mov [dirbcb_offset],bx 0 00009D6A 92 xchg ax,dx ; DX = low word of sector, AX = high word 192 ; mov ah,al ; AH = low byte of high word 0 00009D6B 53 push bx ; save byte offset in sector 0 00009D6C B904FF mov cx,0FF00h+BF_ISDIR ; locate directory sector 0 00009D6F E8[0000] call locate_buffer ; ES:SI -> BCB_ 0 00009D72 5B pop bx ; BX = offset within sector 0 00009D73 06 push es 0 00009D74 1F pop ds ; DS:SI -> buffer control block 0 00009D75 8D7014 lea si,[BCB_DATA + si+bx] ; DS:SI -> data in buffer 0 00009D78 16 push ss 0 00009D79 07 pop es 0 00009D7A BF[1100] mov di,offset dirbuf ; ES:DI -> dir buffer 0 00009D7D 57 push di 0 00009D7E B91000 mov cx,32/2 ; copy into local buffer 0 00009D81 F3A5 rep movsw 0 00009D83 5F pop di ; DI -> dir buffer 0 00009D84 16 push ss 0 00009D85 1F pop ds 0 00009D86 A0[0000] mov al,[adrive] ; remember where we are 0 00009D89 A2[0400] mov [dirbcb],al ; so we can write it back 0 00009D8C C3 ret 212 213 214 ;------------ 215 flush_dirbuf: 216 ;------------ 0 00009D8D B0FF mov al,0FFh 0 00009D8F 8606[0400] xchg al,[dirbcb] ; do we have anything to flush ? 0 00009D93 3A06[0000] cmp al,[adrive] 0 00009D97 7553 jne flush_dir20 ; skip if invalid contents 0 00009D99 BE[0B00] mov si,offset dirbcb_block 0 00009D9C AD lodsw ; get low word of block 0 00009D9D 92 xchg ax,dx ; put it in DX where it belongs 0 00009D9E AD lodsw ; get high word of block 225 ; mov ah,al ; AH:DX -> block to find 0 00009D9F B904FF mov cx,0FF00h+BF_ISDIR ; look for directory 0 00009DA2 E8[0000] call locate_buffer ; locate physical sector 0 00009DA5 26804C0540 or byte [es:BCB_FLAGS + si],BF_DIRTY; mark this buffer as modified 0 00009DAA 8B1E[0F00] mov bx,[dirbcb_offset] ; BX = offset within buffer 0 00009DAE 8D7814 lea di,[BCB_DATA + si+bx] ; ES:DI -> offset in buffer 231 0 00009DB1 268A05 mov al,[es:di] ; AL = 1st character of dir entry 233 0 00009DB4 BE[1100] mov si,offset dirbuf ; get CP/M buffer address 0 00009DB7 B91000 mov cx,32/2 0 00009DBA F3A5 rep movsw ; copy modified entry back 237 0 00009DBC 50 push ax 239 ; xor dh,dh ; we only want HCB_ if it's there 240 ; mov cx,dirbcb_cl ; and it's this cluster 0 00009DBD 30ED xor ch,ch ; we only want HCB_ if it's there 0 00009DBF A1[0500] mov ax,[dirbcb_cl] ; and it's this cluster 0 00009DC2 8B16[0700] mov dx,[dirbcb_cl+2] 0 00009DC6 E83C02 call find_hcb ; does an HCB_ exist for this entry ? 0 00009DC9 58 pop ax 0 00009DCA 7220 jc flush_dir20 ; no, skip update 0 00009DCC 8B3E[0900] mov di,[dirbcb_dcnt] ; we want this dir entry 0 00009DD0 263B7F08 cmp di,[es:HCB_CNT + bx] ; is this within the hashed entries ? 0 00009DD4 7316 jae flush_dir20 ; no, skip the fixup 250 0 00009DD6 84C0 test al,al ; are we using a never used entry ? 0 00009DD8 7506 jnz flush_dir10 ; if so don't trust subsequent hash 0 00009DDA 47 inc di ; codes as they have never been read. 0 00009DDB 26897F08 mov [es:HCB_CNT + bx],di ; Truncate table to force a read of the 0 00009DDF 4F dec di ; next dir entry (which will normally 256 flush_dir10: ; also be never used) 0 00009DE0 D1E7 shl di,1 ; DI = offset of hashed entry 0 00009DE2 8D790A lea di,[HCB_DATA + bx+di] 0 00009DE5 BE[1100] mov si,offset dirbuf ; this is the dir entry 0 00009DE8 E89E02 call mkhsh ; AX = hash code of our entry 0 00009DEB AB stosw ; update hash code for dir entry 262 flush_dir20: 0 00009DEC 1E push ds 0 00009DED 07 pop es ; ES = local data segment 0 00009DEE C3 ret 266 267 ;-------------- 268 discard_dirbuf: 269 ;-------------- 0 00009DEF C606[0400]FF mov byte [dirbcb],0FFh ; invalidate dirbuf 0 00009DF4 C3 ret 272 273 274 ;-------- 275 rd_pcdir: 276 ;-------- 277 ; Exit: AX = offset of directory entry 278 ; = 0 if end of directory 279 280 0 00009DF5 8B1E[3300] mov bx,[dcnt] 0 00009DF9 43 inc bx 0 00009DFA 891E[3300] mov [dcnt],bx ; dcnt=dcnt+1 0 00009DFE E8[0000] call hdsblk ; AX = current directory block 285 ; jz rd_pcdir40 ; skip if we're at the root 0 00009E01 7511 jnz rd_pcdir05 ; not in root dir 0 00009E03 833E[0000]00 cmp word [dirinroot],0 ; is this a FAT32 file system? 0 00009E08 7403 je rd_pcdir04 0 00009E0A E99F00 jmp rd_pcdir40 ; no, skip to normal root dir routine 290 rd_pcdir04: 0 00009E0D A1[0000] mov ax,word ptr [fsroot] ; else treat it as a normal sub directory 0 00009E10 8B16[0200] mov dx,word ptr [fsroot+2] 293 rd_pcdir05: 294 ; we we in a subdirectory - lets follow the chain 295 0 00009E14 A3[3B00] mov [rd_pcdir_cl],ax ; save cluster number for later use 0 00009E17 8916[3D00] mov [rd_pcdir_cl+2],dx 0 00009E1B 91 xchg ax,cx ; keep subdir cluster in CX 0 00009E1C B82000 mov ax,FCBLEN ; AX = size of dir entry 0 00009E1F F7E3 mul bx ; DX:AX = offset of set entry we want 301 ; div clsize ; AX = # clusters to skip, DX = offset in cluster 0 00009E21 51 push cx 0 00009E22 52 push dx 0 00009E23 50 push ax 0 00009E24 FF36[0200] push word [clsize+2] 0 00009E28 FF36[0000] push word [clsize] 0 00009E2C 83EC08 sub sp,8 0 00009E2F E8[0000] call div32 0 00009E32 5A pop dx 0 00009E33 83C402 add sp,2 0 00009E36 58 pop ax 0 00009E37 83C40A add sp,10 0 00009E3A 59 pop cx 0 00009E3B 92 xchg ax,dx ; DX = # to skip, AX = offset in cluster 0 00009E3C 89D7 mov di,dx 0 00009E3E 893E[3F00] mov [rd_pcdir_rel],di ; remember cluster offset 0 00009E42 91 xchg ax,cx ; AX = start of chain, CX = offset in cluster 0 00009E43 A1[3B00] mov ax,[rd_pcdir_cl] 0 00009E46 8B16[3D00] mov dx,[rd_pcdir_cl+2] 0 00009E4A 87D9 xchg bx,cx ; BX = offset in cluster, CX = dcnt 0 00009E4C E344 jcxz rd_pcdir20 ; 1st subdir entry, we are already there 322 ; mov cx,chdblk ; do we already know where we are ? 323 ; jcxz rd_pcdir10 ; if not trace from start of chain 0 00009E4E 833E[3700]00 cmp word [chdblk],0 ; do we already know where we are ? 0 00009E53 7507 jnz rd_pcdir09 0 00009E55 833E[3900]00 cmp word [chdblk+2],0 0 00009E5A 741A jz rd_pcdir10 ; if not trace from start of chain 328 rd_pcdir09: 0 00009E5C 3B3E[4100] cmp di,[rd_pcdir_last]; trying to read cluster before last one? 0 00009E60 7214 jb rd_pcdir10 ; yes, begin at start of chain 331 ; xchg ax,cx ; AX = cluster of last dir entry 0 00009E62 A1[3700] mov ax,[chdblk] 0 00009E65 8B16[3900] mov dx,[chdblk+2] 0 00009E69 85DB test bx,bx ; have we moved onto next cluster? 0 00009E6B 7525 jnz rd_pcdir20 ; no, trust me.. 0 00009E6D 3B3E[4100] cmp di,[rd_pcdir_last]; have we moved onto next cluster? 0 00009E71 741F je rd_pcdir20 ; no, trust me.. 338 ; mov dx,1 ; move on to next entry in the chain 0 00009E73 BF0100 mov di,1 ; move on to next entry in the chain 340 rd_pcdir10: 341 ; or dx,dx ; skip along chain until we arrive 0 00009E76 09FF or di,di ; skip along chain until we arrive 0 00009E78 7418 jz rd_pcdir20 ; at the destination cluster 344 ; dec dx 0 00009E7A 4F dec di 0 00009E7B 53 push bx 347 ; push dx 0 00009E7C 57 push di 0 00009E7D E8[0000] call getnblk ; AX = next cluster in chain 350 ; pop dx 0 00009E80 5F pop di 0 00009E81 5B pop bx 353 ; cmp ax,lastcl ; have we fallen off the end of the chain ? 0 00009E82 3B16[0200] cmp dx,[blastcl+2] ; have we fallen off the end of the chain ? 0 00009E86 72EE jb rd_pcdir10 0 00009E88 771D ja rd_pcdir30 0 00009E8A 3B06[0000] cmp ax,[blastcl] 0 00009E8E 76E6 jbe rd_pcdir10 0 00009E90 EB15 jmp rd_pcdir30 ; yes, set end of directory 360 rd_pcdir20: 0 00009E92 A3[3700] mov [chdblk],ax ; remember this cluster for next time 0 00009E95 8916[3900] mov [chdblk+2],dx 0 00009E99 8B0E[3F00] mov cx,[rd_pcdir_rel] ; save relative position in chain 0 00009E9D 890E[4100] mov [rd_pcdir_last],cx 0 00009EA1 B105 mov cl,FCBSHF ; to divide by fcb size 0 00009EA3 D3EB shr bx,cl ; BX = dir offset in cluster 0 00009EA5 EB0B jmp rd_pcdir50 ; now go and find the entry 368 369 370 rd_pcdir30: 0 00009EA7 E81800 call setenddir ; yes, set dcnt to end of directory 0 00009EAA EB11 jmp rd_pcdir60 373 374 rd_pcdir40: 375 ; we are in the root directory 0 00009EAC 3B1E[0000] cmp bx,[dirinroot] ; end of the root directory ? 0 00009EB0 73F5 jae rd_pcdir30 378 rd_pcdir50: 0 00009EB2 E85FFE call fill_dirbuf ;locate directory entry 0 00009EB5 97 xchg ax,di ; AX -> dir entry 0 00009EB6 833E[3300]FF cmp word [dcnt],ENDDIR 0 00009EBB 7502 jnz rd_pcdir70 383 rd_pcdir60: 0 00009EBD 31C0 xor ax,ax ; return 0 if endofdir 385 rd_pcdir70: 0 00009EBF 89C3 mov bx,ax 0 00009EC1 C3 ret 388 389 390 ;--------- 391 setenddir: ;set dcnt to the end of directory (dcnt = 0ffffh) 392 ;--------- 0 00009EC2 C706[3300]FFFF mov word [dcnt],ENDDIR 0 00009EC8 C706[3700]0000 mov word [chdblk],0 0 00009ECE C706[3900]0000 mov word [chdblk+2],0 0 00009ED4 C3 ret 397 398 399 chk_wild: ;check fcb for ? marks 400 ;-------- 401 ; On Entry: 402 ; bx -> FCB 403 ; On Exit: 404 ; ZF set if ? found 405 ; BX preserved 0 00009ED5 1E push ds 0 00009ED6 07 pop es ; ES -> SYSDAT 0 00009ED7 8D7F01 lea di,[FNAME + bx] ; ES:DI -> name to scan 0 00009EDA B90B00 mov cx,11 0 00009EDD B03F mov al,'?' ; scan for wild cards 0 00009EDF F2AE repne scasb 0 00009EE1 C3 ret 413 414 ;--------- 415 finddfcbf: ; Find matching directory fcb(dfcb) from beginning of directory 416 ;--------- 0 00009EE2 E8DDFF call setenddir ; set up for search first 418 419 ;-------- 420 finddfcb: ; Find matching directory fcb(dfcb) 421 ;-------- 0 00009EE5 B90200 mov cx,2 423 424 ;------ 425 getdir: 426 ;------ 427 ; entry: CH = offset info_fcb (always 0 except from rename) 428 ; CL = search length 429 ; 0 = return next fcb 430 ; 1 = return empty fcb 431 ; 2 = find match (Based on info_fcb) 432 ; 3 = find match? Based on info_fcb 433 ; 434 ; exit: AX,BX,DIRP = pointer to dfcb 435 ; 0 = no match (end of directory) 436 ; other = offset of requested directory entry 437 ; ZF = zero flag is set based on AX 438 ; 439 440 ; Note: The most common call for this function is with CX = 441 ; 2 (match with name, not extent) with 'dcnt' set to 442 ; 0FFFFh (search from beginning of the directory 443 ; (e.g. open, create, delate, rename, etc.). 444 ; Therefore we try to optimize directory searches 445 ; using a dynamic hash table... 446 447 ;struct dirfcb *getdir(offset,srchl); 448 0 00009EE8 833E[3300]FF cmp word [dcnt],0FFFFh ;if ((dcnt == 0xffff) && 450 ; jne gtd_next 0 00009EED 7403 je gtdo10 0 00009EEF E99000 jmp gtd_next 453 gtdo10: 0 00009EF2 890E[0200] mov [hash+2],cx ; Save off calling option 0 00009EF6 31C0 xor ax,ax ; hash code 0 for free entry 0 00009EF8 83F901 cmp cx,1 ; what kind of search? 0 00009EFB 7417 je gtdo15 ; CL=1: find free entry (AX=0) 458 ; jb gtd_next ; CL=0: find any entry (unhashed) 0 00009EFD 7303 jae gtdo12 0 00009EFF E98000 jmp gtd_next ; CL=0: find any entry (unhashed) 461 gtdo12: 0 00009F02 08ED or ch,ch ; name in INFO_FCB+1? 0 00009F04 757C jnz gtd_next ; no, unhashed search 0 00009F06 BB[0000] mov bx,offset info_fcb 0 00009F09 E8C9FF call chk_wild ; wildcards used in search? 0 00009F0C 7470 jz unhshd1 ; yes, can't use hashing 0 00009F0E BE[0100] mov si,offset info_fcb+1 ; else compute hash code 0 00009F11 E87501 call mkhsh ; for name to find 469 gtdo15: 0 00009F14 A3[0000] mov [hash],ax ; save it for search 0 00009F17 E8[0000] call hdsblk ; get directory block 0 00009F1A 83F800 cmp ax,0 ; is this the root dir? 0 00009F1D 7513 jne gtdo3 ; no 0 00009F1F 83FA00 cmp dx,0 0 00009F22 750E jne gtdo3 0 00009F24 833E[0000]00 cmp word [dosfat],FAT32 ; if yes, is this a FAT32 file system? 0 00009F29 7507 jne gtdo3 ; no, then skip 0 00009F2B A1[0000] mov ax,word ptr [fsroot] ; else use the real root cluster number instead 0 00009F2E 8B16[0200] mov dx,word ptr [fsroot+2] 480 gtdo3: 0 00009F32 52 push dx ; save dir block for later 0 00009F33 50 push ax 0 00009F34 E89301 call hashsrch ; try and use hashing to find a match 0 00009F37 7333 jnc gtdo4 ; look closer if we get possible match 0 00009F39 0106[3300] add [dcnt],ax ; else skip known non-matches 0 00009F3D 58 pop ax ; recover current dir block 0 00009F3E 5A pop dx 0 00009F3F 85C0 test ax,ax ; if we are in the root 0 00009F41 7504 jnz gtdo31 0 00009F43 85D2 test dx,dx 0 00009F45 742B jz unhashed ; we must search the hard way 492 gtdo31: 493 ; xchg ax,bx 0 00009F47 52 push dx 0 00009F48 50 push ax 0 00009F49 A1[3300] mov ax,[dcnt] ; should we go onto next cluster ? 0 00009F4C 40 inc ax ; only if next entry is the start 0 00009F4D 31D2 xor dx,dx ; of a cluster 0 00009F4F F736[0000] div word [dirperclu] 500 ; xchg ax,bx 0 00009F53 85D2 test dx,dx ; at start of cluster ? 0 00009F55 58 pop ax 0 00009F56 5A pop dx 0 00009F57 7519 jnz unhashed 0 00009F59 E8[0000] call getnblk ; onto next cluster until we are 506 ; cmp ax,lastcl ; at the end of the chain 0 00009F5C 3B16[0200] cmp dx,[blastcl+2] ; at the end of the chain 0 00009F60 72D0 jb gtdo3 0 00009F62 770E ja unhashed 0 00009F64 3B06[0000] cmp ax,[blastcl] 0 00009F68 76C8 jbe gtdo3 0 00009F6A EB06 jmp unhashed ; out of luck 513 gtdo4: 0 00009F6C 0106[3300] add [dcnt],ax ; we have found a match, so start 0 00009F70 58 pop ax ; search here 0 00009F71 5A pop dx 517 ; jmp unhashed 518 unhashed: ; /* locate entry */ 0 00009F72 C706[3700]0000 mov word [chdblk],0 0 00009F78 C706[3900]0000 mov word [chdblk+2],0 521 unhshd1: 0 00009F7E 8B0E[0200] mov cx,[hash+2] ;} 523 gtd_next: 524 ;-------- 0 00009F82 51 push cx 0 00009F83 E86FFE call rd_pcdir ; Get Next DFCB 0 00009F86 59 pop cx 528 gtd_exit: 0 00009F87 A3[3100] mov [dirp],ax ; assume this is the one 0 00009F8A 89C3 mov bx,ax 0 00009F8C 09C0 or ax,ax ; should we exit with not found ? 0 00009F8E 7405 jz gtd2 0 00009F90 80F900 cmp cl,NEXT ; Caller wishes next dfcb? 0 00009F93 7505 jne gtd3 ; NO 535 gtd2: 0 00009F95 89D8 mov ax,bx ; return BX (DIRP or NULLPTR) 0 00009F97 09C0 or ax,ax ; return ZF (1 = not found) 0 00009F99 C3 ret 539 540 gtd3: 0 00009F9A 80F901 cmp cl,EMPTY ; Caller wishes an empty dfcb? 0 00009F9D 750C jne gtd4 ; NO 0 00009F9F 8A07 mov al,[DNAME + bx] ; Get directory type 0 00009FA1 08C0 or al,al ; Is it free? 0 00009FA3 74F0 jz gtd2 ; YES (00 -> never used) 0 00009FA5 3CE5 cmp al,0E5h ; Is the dfcb empty? 0 00009FA7 74EC je gtd2 ; YES (E5 -> erased) 0 00009FA9 EBD7 jmp gtd_next ; NO, try the next 549 550 gtd4: ; looking for particular entry 0 00009FAB E8[0000] call hdsblk ; Are we at the root? 0 00009FAE 7513 jnz gtd5 ; skip if not 0 00009FB0 833E[0000]00 cmp word [dirinroot],0 ; is this FAT32? 0 00009FB5 740C jz gtd5 ; yes, proceed normally 0 00009FB7 A1[3300] mov ax,[dcnt] ; check for end of directory 0 00009FBA 3B06[0000] cmp ax,[dirinroot] ; have we reached end of root? 0 00009FBE B80000 mov ax,0 ; assume we have 0 00009FC1 73C4 jae gtd_exit ; exit if we have 559 gtd5: 0 00009FC3 8A07 mov al,[DNAME + bx] ; Get dfcb type 0 00009FC5 98 cbw 0 00009FC6 09C0 or ax,ax ; Are we at End Of Directory(EOD) 0 00009FC8 74BD jz gtd_exit ; YES 0 00009FCA 3CE5 cmp al,0E5h ; Is this a free fcb? 0 00009FCC 74B4 je gtd_next ; Yes, try again 0 00009FCE A1[3500] mov ax,[finddfcb_mask] ; do we want labels/pending deletes 0 00009FD1 84670B test [DATTS + bx],ah ; filter out volume labels? 0 00009FD4 75AC jnz gtd_next ; we normally reject them 569 %ifdef DELWATCH 0 00009FD6 98 cbw ; we want labels - do we want 0 00009FD7 85471A test word ptr [DBLOCK1 + bx],ax ; DELWATCH pending deletes 0 00009FDA 75A6 jnz gtd_next ; ie. labels with fat chain 573 %endif 0 00009FDC 51 push cx ; we are interested - but does 0 00009FDD 88E8 mov al,ch ; the name match ? 0 00009FDF 98 cbw 0 00009FE0 05[0100] add ax,offset info_fcb+1 0 00009FE3 31F6 xor si,si ; we want SI = entry to match and 0 00009FE5 96 xchg ax,si ; AL = 0 indicating assumed match 0 00009FE6 B90B00 mov cx,11 ; 11 chars in filename 0 00009FE9 89DF mov di,bx ; ES:DI -> directory entry 582 match3: 0 00009FEB E30B jcxz match4 ; stop if we have done all 11 0 00009FED F3A6 repe cmpsb ; compare if 11 bytes the same 0 00009FEF 7407 je match4 ; skip if all bytes the same 0 00009FF1 807CFF3F cmp byte ptr [si-1],'?' ; else was INFO_FCB byte = '?' 0 00009FF5 74F4 je match3 ; in that case it matches too 0 00009FF7 40 inc ax ; else we didn't match (AL<>0) 589 match4: 0 00009FF8 59 pop cx 0 00009FF9 08C0 or al,al ; did we match ? 592 ; jnz gtd_next ; no, try for another 0 00009FFB 7402 jz match5 0 00009FFD EB83 jmp gtd_next ; no, try for another 595 match5: 0 00009FFF 8B1E[3100] mov bx,[dirp] ; Return (BX) 0 0000A003 EB90 jmp gtd2 598 599 600 601 find_hcb: ; find HCB_ for given drive 602 ;-------- 603 ; On Entry: 604 ; DX:AX = cluster we are looking for 605 ; CH = 00 if exact match required 606 ; FF if we want to recyle oldest HCB_ 607 ; On Exit: 608 ; CY set, AX=0 if HCB_ not found 609 ; CY clear ES:BX = offset of HCB_ (moved to head of list) 610 ; (AX/CX trashed, All other regs preserved) 611 ; 612 0 0000A005 A3[4300] mov [find_hcb_cl],ax 0 0000A008 8916[4500] mov [find_hcb_cl+2],dx 0 0000A00C C41E[0000] les bx,[hashroot] ; get our hashing pointer 0 0000A010 8CC0 mov ax,es 0 0000A012 09D8 or ax,bx ; is hashing enabled ? 0 0000A014 7471 jz find_hcb30 0 0000A016 8A0E[0000] mov cl,[adrive] ; look for this drive 0 0000A01A 8B16[4300] mov dx,[find_hcb_cl] 0 0000A01E 263B5704 cmp dx,[es:HCB_CLU + bx] ; does cluster match? 0 0000A022 7511 jne find_hcb10 ; goto next if not 0 0000A024 8B16[4500] mov dx,[find_hcb_cl+2] 0 0000A028 263B5706 cmp dx,[es:HCB_CLUH + bx] 0 0000A02C 7507 jne find_hcb10 0 0000A02E 263A4F02 cmp cl,[es:HCB_DRV + bx] ; does drive match? 0 0000A032 7501 jne find_hcb10 ; goto next if not 628 ; clc 0 0000A034 C3 ret ; we have a match on the 1st one 630 631 find_hcb10: 632 ; no match, so look futher along the chain 0 0000A035 268B07 mov ax,[es:HCB_LINK + bx] ; onto the next entry 0 0000A038 85C0 test ax,ax ; is there one ? 0 0000A03A 742C jz find_hcb20 0 0000A03C 93 xchg ax,bx ; AX = previous entry, BX = current 0 0000A03D 8B16[4300] mov dx,[find_hcb_cl] 0 0000A041 263B5704 cmp dx,[es:HCB_CLU + bx] ; does cluster match? 0 0000A045 75EE jne find_hcb10 ; goto next if not 0 0000A047 8B16[4500] mov dx,[find_hcb_cl+2] 0 0000A04B 263B5706 cmp dx,[es:HCB_CLUH + bx] 0 0000A04F 75E4 jne find_hcb10 0 0000A051 263A4F02 cmp cl,[es:HCB_DRV + bx] ; does drive match? 0 0000A055 75DE jne find_hcb10 ; goto next if not 645 ; we have a match, but it's not the first so recycle it 0 0000A057 268B0F mov cx,[es:HCB_LINK + bx] ; get link to the rest of the chain 0 0000A05A 93 xchg ax,bx ; BX = previous entry 0 0000A05B 26890F mov [es:HCB_LINK + bx],cx ; unlink ourselves from chain 0 0000A05E 89C3 mov bx,ax ; BX = current entry 0 0000A060 8706[0000] xchg ax,word ptr [hashroot] ; put current entry at the head 0 0000A064 268907 mov [es:HCB_LINK + bx],ax ; and relink the rest of the chain 652 ; clc 0 0000A067 C3 ret 654 655 find_hcb20: 656 ; we have been all along the chain with no luck 0 0000A068 31C0 xor ax,ax 0 0000A06A 84ED test ch,ch ; no HCB_ - do we want to recyle ? 0 0000A06C 7419 jz find_hcb30 ; if not skip 0 0000A06E 26894708 mov [es:HCB_CNT + bx],ax ; we need to recycle oldest HCB_ 0 0000A072 8B16[4300] mov dx,[find_hcb_cl] 0 0000A076 26895704 mov [es:HCB_CLU + bx],dx ; so mark as us, but with nothing 0 0000A07A 8B16[4500] mov dx,[find_hcb_cl+2] 0 0000A07E 26895706 mov [es:HCB_CLUH + bx],dx 0 0000A082 26884F02 mov [es:HCB_DRV + bx],cl ; in it 666 ; clc 0 0000A086 C3 ret 668 669 find_hcb30: 0 0000A087 F9 stc ; return failure 0 0000A088 C3 ret 672 673 ;----- 674 mkhsh: 675 ;----- 676 ; 677 ; entry: SI = 11 byte FCB to convert to hash code 678 ; exit: AX = 1..FFFF is hash code (00/E5 == 0) 679 ; uses: DX 680 ; saves: BX,CX,DI,BP 681 ; 682 ; used for hashing the INFO_FCB & 683 ; directory entries for DOS media 684 0 0000A089 31D2 xor dx,dx ;assume hash code is 0000 0 0000A08B AC lodsb 0 0000A08C 3CE5 cmp al,0E5h ;if deleted file 0 0000A08E 741B je mkhsh2 ; or 0 0000A090 3C00 cmp al,0 ;if virgin entry 0 0000A092 7417 je mkhsh2 ;then hash code = 0; 0 0000A094 51 push cx ;else save CX 0 0000A095 247F and al,7fh 0 0000A097 88C6 mov dh,al ;initialize hash code MSB 0 0000A099 B90A00 mov cx,10 ;involve other 10 characters 695 mkhsh1: 0 0000A09C AC lodsb ;get next character 0 0000A09D D1C2 rol dx,1 ;rotate hash code by one bit 0 0000A09F 247F and al,7fh ;strip top bit off character 0 0000A0A1 30C2 xor dl,al ;XOR the character into the hash code 0 0000A0A3 E2F7 loop mkhsh1 ;repeat for all characters 0 0000A0A5 59 pop cx ;restore CX 0 0000A0A6 85D2 test dx,dx ;test if zero by any chance 0 0000A0A8 7501 jnz mkhsh2 ;skip if non-zero 0 0000A0AA 42 inc dx ;else force it to 1 705 mkhsh2: ;return hash code in AX 0 0000A0AB 92 xchg ax,dx 0 0000A0AC C3 ret 708 709 710 %ifdef DELWATCH 711 Public fixup_hashing 712 ; 713 ; update hashing for current drive if DELWATCH changes a directory entry 714 ; 715 fixup_hashing: 716 ;------------- 717 ; On Entry: 718 ; CX = segment of dir buffer 719 ; DX:AX = cluster to fixup (0 = root) 720 ; DI = directory entry index (clipped to cluster if subdir) 721 ; CX:SI-> dir entry (single entry for hashing) 722 ; 723 ; On Exit: 724 ; None 725 ; 0 0000A0AD 1E push ds 0 0000A0AE 06 push es 728 729 ; xor dh,dh ; we only want HCB_ if it's there 0 0000A0AF 51 push cx ; save seg of dir entry 0 0000A0B0 30ED xor ch,ch ; we only want HCB_ if it's there 0 0000A0B2 E850FF call find_hcb ; does an HCB_ exist for this entry ? 0 0000A0B5 1F pop ds ; DS:SI -> entry to hash 0 0000A0B6 720F jc fixup_ck10 ; not hashed, skip update 0 0000A0B8 263B7F08 cmp di,[es:HCB_CNT + bx] ; is this within the hashed entries ? 0 0000A0BC 7309 jae fixup_ck10 ; no, skip the fixup 0 0000A0BE E8C8FF call mkhsh ; cx = hash code of our entry 738 0 0000A0C1 D1E7 shl di,1 ; DI = offset of hashed entry 0 0000A0C3 8D790A lea di,[HCB_DATA + bx+di] 0 0000A0C6 AB stosw ; update hash code for dir entry 742 743 fixup_ck10: 0 0000A0C7 07 pop es 0 0000A0C8 1F pop ds 0 0000A0C9 C3 ret ; no 747 %endif 748 749 750 751 hashsrch: 752 ;-------- 753 ; entry: DX:AX = starting cluster of directory 754 ; exit: AX is possible match index 755 ; 756 ; mov dh,0FFh ; we want HCB_ even if it's recycled 0 0000A0CA B5FF mov ch,0FFh ; we want HCB_ even if it's recycled 758 ; xchg ax,cx ; and this block 0 0000A0CC E836FF call find_hcb ; does an HCB_ exist for this entry ? 760 ; mov ax,0 ; assume unhashed search required 0 0000A0CF 7218 jc hashsrch20 ; start one if no hashing 762 hashsrch10: 0 0000A0D1 268B4F08 mov cx,[es:HCB_CNT + bx] ; we have this many entries hashed 0 0000A0D5 E316 jcxz hashsrch30 ; skip if nothing hashed yet 0 0000A0D7 A1[0000] mov ax,[hash] ; look for this hash code 0 0000A0DA 8D7F0A lea di,[HCB_DATA + bx] ; DI = offset of start of search 0 0000A0DD F2AF repne scasw ; try to find a match 0 0000A0DF 750C jne hashsrch30 ; skip if no match found 0 0000A0E1 8D470C lea ax,[HCB_DATA+2 + bx] ; find word offset of match 0 0000A0E4 97 xchg ax,di ; return matching index 0 0000A0E5 29F8 sub ax,di 0 0000A0E7 D1E8 shr ax,1 ; make dir offset 773 hashsrch20: 0 0000A0E9 1E push ds 0 0000A0EA 07 pop es 0 0000A0EB F8 clc ; we have found it 0 0000A0EC C3 ret 778 779 hashsrch30: 0 0000A0ED E80900 call rehash_entry ; try and hash another entry 0 0000A0F0 73DF jnc hashsrch10 ; look again if we succeeded 782 0 0000A0F2 268B4708 mov ax,[es:HCB_CNT + bx] ; failure, so return # to skip 0 0000A0F6 1E push ds 0 0000A0F7 07 pop es 786 ; stc ; for quicker search 0 0000A0F8 C3 ret 788 789 790 rehash_entry: 791 ;------------ 792 ; entry: ES:BX -> HCB 793 ; AX = hash cluster number ??? This does not seem to be used... 794 0 0000A0F9 E87900 call hash_entries_to_do ; how many entries still to hash ? 0 0000A0FC E375 jcxz rehash_entry40 ; if we have hashed them all exit 797 0 0000A0FE FF36[3300] push word [dcnt] ; save directory count 799 0 0000A102 A1[3300] mov ax,[dcnt] ; get previous position 0 0000A105 40 inc ax ; we start looking here 0 0000A106 31D2 xor dx,dx 0 0000A108 F736[0000] div word [dirperclu] ; mask to start of cluster 0 0000A10C F726[0000] mul word [dirperclu] 0 0000A110 26034708 add ax,[es:HCB_CNT + bx] ; skip entries we already have 0 0000A114 48 dec ax ; make previous entry BEFORE this 0 0000A115 A3[3300] mov [dcnt],ax 0 0000A118 C706[3700]0000 mov word [chdblk],0 ; non-sequential access 0 0000A11E C706[3900]0000 mov word [chdblk+2],0 0 0000A124 83F910 cmp cx,512/32 ; don't try reading more than 512 bytes 0 0000A127 7203 jb rehash_entry20 ; at a time - then with 512 byte secs 0 0000A129 B91000 mov cx,512/32 ; we only read when we 813 rehash_entry20: 0 0000A12C 06 push es 0 0000A12D 53 push bx ; save hash control pointer 0 0000A12E 51 push cx ; save # entries to do 0 0000A12F 1E push ds 0 0000A130 07 pop es ; back to small model 0 0000A131 31C9 xor cx,cx ; return any entry 0 0000A133 E84CFE call gtd_next ; unhashed search 0 0000A136 59 pop cx ; restore # entries to do 0 0000A137 5B pop bx ; restore hash control pointer 0 0000A138 07 pop es 0 0000A139 85C0 test ax,ax ; anything found 0 0000A13B 7424 jz rehash_entry30 ; end of directory 0 0000A13D 96 xchg ax,si ; else get directory pointer 0 0000A13E 268B7F08 mov di,[es:HCB_CNT + bx] 0 0000A142 D1E7 shl di,1 ; DI -> 1st new entry 0 0000A144 8D790A lea di,[HCB_DATA + bx+di] 0 0000A147 56 push si 0 0000A148 E83EFF call mkhsh ; else calculate hash into AX 0 0000A14B AB stosw ; add it to hash table 0 0000A14C 26FF4708 inc word [es:HCB_CNT + bx] ; remember we did 0 0000A150 5E pop si 0 0000A151 AC lodsb ; get 1st byte of hashed entry 0 0000A152 84C0 test al,al ; is it zero (ie. never used)? 0 0000A154 E0D6 loopne rehash_entry20 ; get all hash codes 0 0000A156 E309 jcxz rehash_entry30 ; all done ? 0 0000A158 E81A00 call hash_entries_to_do ; how many entries still to hash ? 0 0000A15B 26014F08 add [es:HCB_CNT + bx],cx ; we will do them all.. 0 0000A15F F3AB rep stosw ; zap rest of cluster 842 rehash_entry30: 0 0000A161 8F06[3300] pop word [dcnt] ; restore count 0 0000A165 C706[3700]0000 mov word [chdblk],0 ; non-sequential access 0 0000A16B C706[3900]0000 mov word [chdblk+2],0 0 0000A171 F8 clc ; we have new hashing codes 0 0000A172 C3 ret ; HCB updated with new cluster 848 849 rehash_entry40: 0 0000A173 F9 stc ; cannot hash no more... 0 0000A174 C3 ret 852 853 hash_entries_to_do: 854 ;------------------ 855 ; On Entry: 856 ; ES:BX -> HCB_ 857 ; On Exit: 858 ; CX = maximum possible entries we still need to hash for HCB_ 859 ; (All other regs preserved) 860 ; 0 0000A175 8B0E[0000] mov cx,[dirinroot] ; assume root dir 0 0000A179 26837F0400 cmp word [es:HCB_CLU + bx],0 ; was it ? 863 ; je hash_etd10 0 0000A17E 750E jne hash_etd09 ; no, proceed normally 0 0000A180 26837F0600 cmp word [es:HCB_CLUH + bx],0 0 0000A185 7507 jne hash_etd09 0 0000A187 833E[0000]00 cmp word [dirinroot],0 ; is this FAT32? 0 0000A18C 7504 jne hash_etd10 ; no, proceed with FAT12/16 routine 869 hash_etd09: 0 0000A18E 8B0E[0000] mov cx,[dirperclu] ; subdir, so cluster limit 871 hash_etd10: 0 0000A192 3B0E[0000] cmp cx,[hashmax] ; do we support this many ? 0 0000A196 7204 jb hash_etd20 ; yes, skip it 0 0000A198 8B0E[0000] mov cx,[hashmax] ; else limit it to this many 875 hash_etd20: 0 0000A19C 262B4F08 sub cx,[es:HCB_CNT + bx] ; subtract number we have already done 0 0000A1A0 C3 ret 878 879 880 881 hshdscrd: 882 ;-------- 883 ; purge hash blocks for physical drive 884 ; On Entry: 885 ; AL = drive to discard (FF = all drives) 886 ; On Exit: 887 ; None (All regs preserved) 888 0 0000A1A1 1E push ds 0 0000A1A2 53 push bx 0 0000A1A3 C51E[0000] lds bx,[hashroot] ; get root of hash codes 892 hshdsc1: 0 0000A1A7 85DB test bx,bx 0 0000A1A9 7411 jz hshdsc4 ; all blocks done 0 0000A1AB 3CFF cmp al,0FFh ; FF means discard all drives 0 0000A1AD 7405 je hshdsc2 0 0000A1AF 3A4702 cmp al,[HCB_DRV + bx] ; check if matching drive 0 0000A1B2 7504 jne hshdsc3 899 hshdsc2: 0 0000A1B4 C64702FF mov byte [HCB_DRV + bx],0ffh ; h->hd = 0xff; 901 hshdsc3: 0 0000A1B8 8B1F mov bx,[HCB_LINK + bx] ; get next hash code block 0 0000A1BA EBEB jmp hshdsc1 904 hshdsc4: 0 0000A1BC 5B pop bx 0 0000A1BD 1F pop ds 0 0000A1BE C3 ret 908 909 910 911 enlarge_root: 912 %ifdef DELWATCH 0 0000A1BF B404 mov ah,DELW_FREERD ; lets ask DELWATCH if it can 0 0000A1C1 A0[0000] mov al,[adrive] ; free a root directory entry 0 0000A1C4 36FF1E[0000] call far [ss:fdos_stub] ; for this drive 0 0000A1C9 7307 jnc allocdir ; it says it has so try again 917 %endif 918 allocdir_err: 0 0000A1CB 58 pop ax ; discard return address 0 0000A1CC B8AEFF mov ax,ED_MAKE 0 0000A1CF E9[0000] jmp fdos_error ; return "cannot make dir entry" 922 923 924 ;-------- 925 allocdir: ; Called by rename and MAKE 926 ;-------- 0 0000A1D2 E8EDFC call setenddir ; search for first match 0 0000A1D5 B90100 mov cx,1 ; return empty fcb 0 0000A1D8 E80DFD call getdir ; is there an empty fcb? 0 0000A1DB 7401 jz allocdir10 ; if so use that 0 0000A1DD C3 ret 932 allocdir10: 0 0000A1DE E8[0000] call hdsblk ; Are we at the root? 0 0000A1E1 750E jnz allocdir20 ; no, proceed 0 0000A1E3 833E[0000]00 cmp word [dosfat],FAT32 ; FAT32 file system? 936 ; jz enlarge_root ; YES -- Report error(no room) 0 0000A1E8 75D5 jne enlarge_root ; NO -- Report error(no room) 0 0000A1EA 8B16[0200] mov dx,word ptr [fsroot+2] ; use starting cluster of root dir 0 0000A1EE A1[0000] mov ax,word ptr [fsroot] 940 941 ; We are in a subdirectory so enlarge it 942 ; AX has 1st block of subdirectory NOTE -- AX is never 943 ; above 'lastcl' on entry. 944 allocdir20: 945 ; cmp ax,lastcl ; Are we at end of subdirectory? 0 0000A1F1 3B16[0200] cmp dx,[blastcl+2] ; Are we at end of subdirectory? 0 0000A1F5 7711 ja allocdir30 ; YES 0 0000A1F7 7206 jb allocdir25 0 0000A1F9 3B06[0000] cmp ax,[blastcl] 0 0000A1FD 7709 ja allocdir30 951 allocdir25: 0 0000A1FF 52 push dx 0 0000A200 50 push ax 0 0000A201 E8[0000] call getnblk ; NO -- get next block then 0 0000A204 5B pop bx 0 0000A205 59 pop cx 0 0000A206 EBE9 jmp allocdir20 958 959 allocdir30: 0 0000A208 51 push cx 0 0000A209 53 push bx ; save last block number 0 0000A20A 93 xchg ax,bx ; Get a new block (start from old) 0 0000A20B 87D1 xchg dx,cx 0 0000A20D E8[0000] call alloc_cluster 0 0000A210 5B pop bx 0 0000A211 59 pop cx 0 0000A212 72B7 jc allocdir_err ; Report Error(no room on disk) 0 0000A214 52 push dx 0 0000A215 50 push ax ; save new block 0 0000A216 93 xchg ax,bx 0 0000A217 87D1 xchg dx,cx 0 0000A219 E8[0000] call fixfat ; Update fat (AX,BX) old last block 973 ; points to new last block 0 0000A21C 58 pop ax ; Get new last block 0 0000A21D 5A pop dx 0 0000A21E 52 push dx 0 0000A21F 50 push ax 0 0000A220 31C9 xor cx,cx 0 0000A222 8B1E[0000] mov bx,[dosfat] ; 12 or 16 bit fat 0 0000A226 833E[0000]00 cmp word [dosfat],FAT32 ; FAT32 file system 0 0000A22B 7505 jne allocdir35 ; no, then proceed with this value 0 0000A22D BBFFFF mov bx,0ffffh ; else use this one instead 0 0000A230 89D9 mov cx,bx 984 allocdir35: 0 0000A232 E8[0000] call fixfat ; Update fat (AX,BX) new last block 986 ; has end of cluster marker 0 0000A235 E8[0000] call update_fat ; Write out to disk 0 0000A238 58 pop ax ; Get new last block 0 0000A239 5A pop dx 0 0000A23A E8[0000] call zeroblk ; Zero it out 0 0000A23D E882FC call setenddir ; Set up for search first 0 0000A240 B90100 mov cx,1 ; Find empty fcb 0 0000A243 E9A2FC jmp getdir ; Can not return with not found error 994 995 BDOS_CODE ends 996 997 END === Trace listing source: drdos/bin/buffers.lst 1 ;title 'BUFFERS - buffer handling routines' 2 ; File : $BUFFERS.ASM$ 3 ; 4 ; Description : 5 ; 6 ; Original Author : DIGITAL RESEARCH 7 ; 8 ; Last Edited By : $CALDERA$ 9 ; 10 ;-----------------------------------------------------------------------; 11 ; Copyright Work of Caldera, Inc. All Rights Reserved. 12 ; 13 ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, 14 ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. 15 ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES 16 ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF 17 ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO 18 ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE 19 ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE 20 ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, 21 ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, 22 ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, 23 ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF 24 ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT 25 ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND 26 ; CIVIL LIABILITY. 27 ;-----------------------------------------------------------------------; 28 ; 29 ; *** Current Edit History *** 30 ; *** End of Current Edit History *** 31 ; 32 ; $Log$ 33 ; 34 ; BUFFERS.A86 1.13 94/11/30 16:26:08 35 ; added support for using multiple FAT copies on reads if one fails 36 ; BUFFERS.A86 1.12 93/08/06 16:19:11 37 ; make geblk public 38 ; BUFFERS.A86 1.8 93/07/07 21:06:25 39 ; Smirnoff'd 40 ; BUFFERS.A86 1.6 93/03/16 22:30:29 41 ; UNDELETE support changes 42 ; BUFFERS.A86 1.5 93/03/05 18:00:26 43 ; Fix bug clearing cluster of new sub directory 44 ; ENDLOG 45 46 ; Date Who Modification 47 ; --------- --- --------------------------------------- 48 ; 9 Sep 91 Initial version created for VLADIVAR 49 ; 3 mar 93 correct zeroblk bug 50 51 group PCMCODE BDOS_CODE 52 group PCMDATA BDOS_DATA PCMODE_DATA 53 54 [list -] 59 === Switch to base=00C180h -> "PCMODE_DATA" 60 section PCMODE_DATA public align=2 class=DATA 61 62 extrn current_ddsc:dword 63 %ifdef DELWATCH 64 extrn fdos_stub:dword 65 %endif 66 PCMODE_DATA ends 67 68 === Switch to base=00C180h -> "BDOS_DATA" 69 section BDOS_DATA public align=2 class=DATA 70 0 000019A6 00000000 fatrec dw 2 dup (0) ; current FAT record 72 0 000019AA 00 fatbytl db 0 ; low byte of split FAT entry 0 000019AB 00 fatbyth db 0 ; high byte of split FAT entry 0 000019AC 00 split_fat db 0 ; 0/FFh to indicate split entry 0 000019AD 00 tag_flg db 0 ; do not read FAT sector, just tag it 77 0 000019AE 00000000 alloc_clus_cl dw 0,0 0 000019B2 00000000 alloc_chain_cl dw 0,0 0 000019B6 00000000 delfat_cl dw 0,0 81 82 extrn adrive:byte 83 EXTRN chdblk:WORD 84 EXTRN clsize:WORD 85 EXTRN cur_dma:WORD 86 EXTRN cur_dma_seg:WORD 87 extrn dosfat:WORD 88 EXTRN fatadd:WORD 89 extrn lastcl:word 90 extrn blastcl:word 91 EXTRN mult_sec:WORD 92 EXTRN nfatrecs:WORD 93 EXTRN nfats:WORD 94 extrn pblock:dword 95 extrn physical_drv:byte 96 extrn psecsiz:word 97 extrn rwmode:byte ; data/directory/FAT, read/write 98 extrn secperclu:word 99 extrn bcb_root:dword ; PCMODE disk buffer root 100 extrn deblock_seg:word 101 BDOS_DATA ends 102 === Switch to base=000000h -> "BDOS_CODE" 103 section BDOS_CODE public align=2 class=CODE 104 ASSUME DS:PCMDATA 105 106 extrn clus2sec:near 107 extrn discard_dirbuf:near 108 extrn fdos_error:near 109 extrn flush_dirbuf:near 110 extrn hshdscrd:near 111 extrn read_block:near 112 extrn select_adrive:near ; select drive AL 113 extrn write_block:near 114 extrn output_hex:near 115 extrn div32:near 116 117 public alloc_cluster ; allocate data block 118 public alloc_chain ; allocate a chain 119 public buffers_check ; check if buffers exist for this drive 120 PUBLIC delfat ; release data blocks 121 PUBLIC discard_all ; discard all buffers on ADRIVE 122 public discard_dir ; discard directory buffers on ADRIVE 123 public discard_dirty ; discard directory buffers on ADRIVE 124 PUBLIC fixfat ; set value of FAT entry 125 public flush_drive ; flush buffers to disk 126 public locate_buffer ; locate a buffer 127 PUBLIC update_dat ; flush write pending buffers 128 public update_ddsc_free ; count free blocks on drive 129 PUBLIC update_dir ; update directory entry 130 PUBLIC update_fat ; write out modified FAT records 131 public zeroblk ; zero cluster (MKDIR) 132 %ifdef DELWATCH 133 public allocate_cluster ; allocate free cluster on adrive 134 public change_fat_entry ; write a new value into the FAT 135 %endif 136 137 138 139 140 update_ddsc_free: 141 ;---------------- 142 ; make sure DDSC_FREE is up to date 143 ; a by-product of this is to checksum the FAT, so we can spot changes 144 ; of removable media 0 0000A246 06 push es 0 0000A247 36C41E[0000] les bx,[ss:current_ddsc] 147 ; mov cx,es:DDSC_FREE[bx] ; get current free space 148 ; jcxz update_ddsc_free30 ; if none recount to make sure 0 0000A24C 833E[0000]00 cmp word [dosfat],FAT32 ; FAT32 drive? 0 0000A251 7410 je update_ddsc_free03 ; yes 0 0000A253 26837F1F00 cmp word ptr [es:DDSC_FREE + bx],0 ; check current free space 0 0000A258 7440 je update_ddsc_free30 ; if none recount to make sure 0 0000A25A 26837F1FFF cmp word ptr [es:DDSC_FREE + bx],0ffffh ; is count uninitialised ? (=FFFF) 0 0000A25F 7439 je update_ddsc_free30 ; if so better count the free space 0 0000A261 EB1C jmp update_ddsc_free10 ; skip 32-bit free blocks count 156 update_ddsc_free03: 0 0000A263 26837F2300 cmp word ptr [es:DDSC_BFREE+2 + bx],0 ; check current free space 0 0000A268 7507 jne update_ddsc_free05 0 0000A26A 26837F2100 cmp word ptr [es:DDSC_BFREE + bx],0 0 0000A26F 7429 je update_ddsc_free30 ; if none recount to make sure 161 update_ddsc_free05: 162 ; inc cx ; is count uninitialised ? (=FFFF) 0 0000A271 26837F23FF cmp word ptr [es:DDSC_BFREE+2 + bx],0ffffh ; is count uninitialised ? (=FFFF) 0 0000A276 7507 jne update_ddsc_free10 0 0000A278 26837F21FF cmp word ptr [es:DDSC_BFREE + bx],0ffffh 0 0000A27D 741B jz update_ddsc_free30 ; if so better count the free space 167 update_ddsc_free10: 0 0000A27F 833E[0000]00 cmp word [dosfat],FAT32 ; FAT32 drive? 0 0000A284 7512 jne update_ddsc_free16 ; no, then 16-bit value is exact 0 0000A286 268B4721 mov ax,word ptr [es:DDSC_BFREE + bx] 0 0000A28A 26837F2300 cmp word ptr [es:DDSC_BFREE+2 + bx],0 ; is the 16-bit value valid? 0 0000A28F 7403 je update_ddsc_free15 ; yes, then leave it 0 0000A291 B8FEFF mov ax,0fffeh ; else use a fake value 174 update_ddsc_free15: 0 0000A294 2689471F mov [es:DDSC_FREE + bx],ax ; update the 16-bit value as well 176 update_ddsc_free16: 0 0000A298 07 pop es 0 0000A299 C3 ret 179 180 update_ddsc_free30: 181 ; rebuild our free space count 0 0000A29A 833E[0000]00 cmp word [dosfat],FAT32 ; FAT32 drive? 0 0000A29F 7534 jne update_ddsc_free33 ; no, then skip 0 0000A2A1 26837F2300 cmp word ptr [es:DDSC_BFREE+2 + bx],0 ; out of free space? 0 0000A2A6 7507 jne update_ddsc_free31 ; no, just unknown 0 0000A2A8 26837F2100 cmp word ptr [es:DDSC_BFREE + bx],0 0 0000A2AD 7426 je update_ddsc_free33 ; yes, then recount 188 update_ddsc_free31: ; else try FS info sector value 0 0000A2AF 26837F27FF cmp word [es:DDSC_FSINFO + bx],0ffffh;FS info sector present? 0 0000A2B4 741F je update_ddsc_free33 ; no, then do not try to read from it 0 0000A2B6 E89707 call read_fsinfo05 ; read the info block first, if one exists 0 0000A2B9 26837F2300 cmp word ptr [es:DDSC_BFREE+2 + bx],0 ; is free block count on disk zero? 0 0000A2BE 7507 jne update_ddsc_free32 ; no 0 0000A2C0 26837F2100 cmp word ptr [es:DDSC_BFREE + bx],0 0 0000A2C5 740E je update_ddsc_free33 ; yes, recount to make sure 196 update_ddsc_free32: 0 0000A2C7 26837F23FF cmp word ptr [es:DDSC_BFREE+2 + bx],0ffffh ; still uninitialized? 0 0000A2CC 75B1 jne update_ddsc_free10 ; no, then use this value 0 0000A2CE 26837F21FF cmp word ptr [es:DDSC_BFREE + bx],0ffffh 0 0000A2D3 75AA jne update_ddsc_free10 201 update_ddsc_free33: ; else really rebuild it 0 0000A2D5 31C0 xor ax,ax ; assume no free space yet 0 0000A2D7 31D2 xor dx,dx 0 0000A2D9 833E[0000]00 cmp word [dosfat],FAT32 ; FAT32 drive? 0 0000A2DE 750A jne update_ddsc_free35 ; no, then skip 0 0000A2E0 8D7F3B lea di,[DDSC_BBLOCK + bx] ; ES:DI -> DDSC_BBLOCK 0 0000A2E3 AB stosw ; DDSC_BBLOCK = 0 0 0000A2E4 AB stosw 0 0000A2E5 8D7F21 lea di,[DDSC_BFREE + bx] ; ES:DI -> DDSC_BFREE 0 0000A2E8 AB stosw ; DDSC_BFREE = 0 0 0000A2E9 AB stosw 212 update_ddsc_free35: 0 0000A2EA 8D7F1D lea di,[DDSC_BLOCK + bx] ; ES:DI -> DDSC_BLOCK 0 0000A2ED AB stosw ; DDSC_BLOCK = 0 0 0000A2EE AB stosw ; DDSC_FREE = 0 0 0000A2EF 40 inc ax ; skip reserved block #'s 0 and 1 217 update_ddsc_free40: 218 ; inc ax ; move to next data block # 0 0000A2F0 83C001 add ax,1 ; move to next data block # 0 0000A2F3 83D200 adc dx,0 221 ; cmp ax,lastcl ; are we beyond end of disk 0 0000A2F6 3B16[0200] cmp dx,[blastcl+2] ; are we beyond end of disk 223 ; ja update_ddsc_free10 ; stop if all free blocks counted 0 0000A2FA 7728 ja update_ddsc_free50 ; stop if all free blocks counted 0 0000A2FC 7206 jb update_ddsc_free45 0 0000A2FE 3B06[0000] cmp ax,[blastcl] 227 ; ja update_ddsc_free10 0 0000A302 7720 ja update_ddsc_free50 229 update_ddsc_free45: 230 ; push ax ; save current index 0 0000A304 52 push dx ; save current index 0 0000A305 50 push ax 0 0000A306 E8CD00 call getblk ; get contents of FAT entry, update ZF 0 0000A309 58 pop ax ; restore current FAT index 0 0000A30A 5A pop dx 0 0000A30B 75E3 jnz update_ddsc_free40 ; try next block if not free 0 0000A30D 26FF471F inc word [es:DDSC_FREE + bx] ; one more free block 0 0000A311 833E[0000]00 cmp word [dosfat],FAT32 ; FAT32 drive? 0 0000A316 75D8 jne update_ddsc_free40 ; no, then skip 0 0000A318 2683472101 add word ptr [es:DDSC_BFREE + bx],1 ; one more free block 0 0000A31D 2683572300 adc word ptr [es:DDSC_BFREE+2 + bx],0 0 0000A322 EBCC jmp update_ddsc_free40 ; try next block 243 update_ddsc_free50: 0 0000A324 26837F27FF cmp word [es:DDSC_FSINFO + bx],0ffffh;FS info sector present? 0 0000A329 7403 je update_ddsc_free55 ; no, then do not write to it, either 0 0000A32B E85107 call write_fsinfo ; write a new FS info block first if applicable 247 update_ddsc_free55: 0 0000A32E E94EFF jmp update_ddsc_free10 249 250 251 discard_dirty: 252 ;------------- 253 ; This gets called after a write-protect error is returned 254 0 0000A331 B440 mov ah,BF_DIRTY ; discard dirty FAT, dir & data 0 0000A333 EB06 jmp discard_buffers 257 258 discard_all: 259 ;----------- 0 0000A335 B40E mov ah,BF_ISFAT+BF_ISDIR+BF_ISDAT 0 0000A337 EB02 jmp discard_buffers ; discard all the buffers 262 263 discard_dir: 264 ;----------- 0 0000A339 B404 mov ah,BF_ISDIR ; dir only, leave data and FAT 266 ; jmp discard_buffers 267 268 discard_buffers: 269 ;--------------- 270 ; entry: adrive = drive to discard 271 ; AH = flags for type to discard i.e. BF_ISFAT, etc. 272 0 0000A33B A0[0000] mov al,[adrive] ; get the work drive 0 0000A33E E8[0000] call discard_dirbuf ; discard 32-byte directory buffer 0 0000A341 E8[0000] call hshdscrd ; discard hashing info for drive 0 0000A344 C436[0000] les si,[bcb_root] ; get first buffer 277 discard_buffers10: 0 0000A348 263A4404 cmp al,[es:BCB_DRV + si] ; does the drive match? 0 0000A34C 7510 jne discard_buffers20 ; try next one if not 0 0000A34E 26846405 test ah,[es:BCB_FLAGS + si] ; does the type match? 0 0000A352 740A jz discard_buffers20 ; try next one if not 0 0000A354 26C64404FF mov byte [es:BCB_DRV + si],0FFh ; else discard the buffer 0 0000A359 26C6440500 mov byte [es:BCB_FLAGS + si],0 284 discard_buffers20: 0 0000A35E 268B34 mov si,[es:BCB_NEXT + si] ; get next buffer address 0 0000A361 3B36[0000] cmp si,word ptr [bcb_root] 0 0000A365 75E1 jne discard_buffers10 ; and repeat until all done 288 discard_buffers30: 0 0000A367 1E push ds 0 0000A368 07 pop es ; restore ES and return 0 0000A369 C3 ret 292 293 294 ;------------- 295 buffers_check: 296 ;------------- 297 ; entry: AL = drive to check (preserved) 298 ; AH = flags 299 ; exit: ZF = 1 if all buffers clean on this drive 300 0 0000A36A 1E push ds ; we use DS here cause it's quicker... 0 0000A36B 36C536[0000] lds si,[ss:bcb_root] ; start with most recently used 303 buffers_check10: 0 0000A370 3A4404 cmp al,[BCB_DRV + si] ; check if for different drive 0 0000A373 7505 jne buffers_check20 ; skip if not our problem 0 0000A375 846405 test ah,[BCB_FLAGS + si] ; test if its one we are looking for 0 0000A378 750B jnz buffers_check30 ; return with non-zero condition 308 buffers_check20: 0 0000A37A 8B34 mov si,[BCB_NEXT + si] ; get next buffer address 0 0000A37C 363B36[0000] cmp si,word ptr [ss:bcb_root] 0 0000A381 75ED jne buffers_check10 ; loop back if more to do 0 0000A383 31D2 xor dx,dx ; set ZF = 1 313 buffers_check30: 0 0000A385 1F pop ds ; restore DS after BCBs done 0 0000A386 C3 ret 316 317 318 319 ; entry: DX:AX = first block to release 320 ; exit: DX:AX and following released 321 322 delfat: ; release chain of clusters 323 ;------ 324 ; cmp ax,2 ; is block number too small? 0 0000A387 83FA00 cmp dx,0 ; is block number too small? 0 0000A38A 7505 jne delfat05 ; no, proceed 0 0000A38C 83F802 cmp ax,2 0 0000A38F 722C jb delfat10 ; yes, then stop it 329 delfat05: 330 ; cmp ax,lastcl ; is block number too large? 0 0000A391 3B16[0200] cmp dx,[blastcl+2] ; is block number too large? 0 0000A395 7726 ja delfat10 ; yes, then stop it 0 0000A397 7206 jb delfat06 ; no, proceed 0 0000A399 3B06[0000] cmp ax,[blastcl] 0 0000A39D 771E ja delfat10 336 delfat06: 0 0000A39F 52 push dx 0 0000A3A0 50 push ax ; else save the number 0 0000A3A1 E83200 call getblk ; get the next link 340 ; xchg ax,cx ; CX = link 0 0000A3A4 A3[1000] mov [delfat_cl],ax ; DX:AX = link 0 0000A3A7 8916[1200] mov [delfat_cl+2],dx 0 0000A3AB 58 pop ax ; AX = this block 0 0000A3AC 5A pop dx 0 0000A3AD 29DB sub bx,bx ; set it to 0000 0 0000A3AF 29C9 sub cx,cx 347 ; push cx ; save the link for next pass 0 0000A3B1 E80F02 call fixfat ; release the block 349 ; pop ax ; AX = next block or end 0 0000A3B4 A1[1000] mov ax,[delfat_cl] 0 0000A3B7 8B16[1200] mov dx,[delfat_cl+2] 0 0000A3BB EBCA jmp delfat ; try again until all released 353 delfat10: ; all blocks in chain freed 0 0000A3BD C3 ret 355 356 357 ; On Entry: 358 ; DX:AX = block to read 359 ; On Exit: 360 ; DX:AX = next FAT block index 361 ; 362 Public getnblk 363 364 getnblk: ;UWORD getnblk(blk); 365 ;------- 366 ; 0 0000A3BE 50 push ax 0 0000A3BF E81400 call getblk ; get current setting 0 0000A3C2 5B pop bx 0 0000A3C3 7401 jz getnblk10 ; return if something there 0 0000A3C5 C3 ret 372 getnblk10: 0 0000A3C6 A1[0000] mov ax,[dosfat] ; if unallocated then allocate it 0 0000A3C9 52 push dx 0 0000A3CA 50 push ax 0 0000A3CB 93 xchg ax,bx ; DX:AX = blk, CX:BX = i 0 0000A3CC 87D1 xchg dx,cx 0 0000A3CE E8F201 call fixfat 0 0000A3D1 58 pop ax 0 0000A3D2 5A pop dx 381 ; mov dx,ax ; DX = end of chain 0 0000A3D3 31C9 xor cx,cx ; no blocks follow this one 0 0000A3D5 C3 ret 384 385 ; On Entry: 386 ; DX:AX = block to read 387 ; On Exit: 388 ; DX:AX = contents 389 ; ZF = 1 if AX == 0000h (disk full) 390 391 Public getblk 392 393 ;------ 394 getblk: 395 ;------ 0 0000A3D6 06 push es 0 0000A3D7 53 push bx 0 0000A3D8 E81B03 call fatptr ; get address of block DX:AX in buffer 0 0000A3DB 268B07 mov ax,[es:bx] ; get the word from FAT 0 0000A3DE 7522 jnz getblk10 ; skip if on odd address (must be 12 bit) 0 0000A3E0 813E[0000]FF0F cmp word [dosfat],FAT12 ; else check if 16/32 or 12 bit 0 0000A3E6 7422 je getblk20 ; skip if even 12 bit 0 0000A3E8 31D2 xor dx,dx 0 0000A3EA 833E[0000]00 cmp word [dosfat],FAT32 ; check if 32 bit 0 0000A3EF 7508 jne getblk05 0 0000A3F1 268B5702 mov dx,[es:2 + bx] 0 0000A3F5 81E2FF0F and dx,0fffh ; mask out reserved bits 408 getblk05: 0 0000A3F9 5B pop bx 0 0000A3FA 07 pop es 0 0000A3FB 85D2 test dx,dx ; update ZF 0 0000A3FD 7502 jnz getblk06 0 0000A3FF 85C0 test ax,ax ; update ZF 414 getblk06: 0 0000A401 C3 ret 416 417 getblk10: 0 0000A402 D1E8 shr ax,1 ; shift top 12 bits down 0 0000A404 D1E8 shr ax,1 0 0000A406 D1E8 shr ax,1 0 0000A408 D1E8 shr ax,1 422 getblk20: 0 0000A40A 31D2 xor dx,dx 0 0000A40C 25FF0F and ax,0FFFh ; leave bottom 12 bits only 0 0000A40F 5B pop bx 0 0000A410 07 pop es 0 0000A411 C3 ret 428 429 430 431 alloc_cluster: 432 ;------------- 433 ; On Entry: 434 ; DX:AX = previous cluster (hint for desired start) 435 ; On Exit: 436 ; DX:AX = start of chain 437 ; CY set on failure 438 ; 0 0000A412 B90100 mov cx,1 440 ; jmp alloc_chain 441 442 alloc_chain: 443 ;----------- 444 ; On Entry: 445 ; DX:AX = previous cluster (hint for desired start) 446 ; CX = # clusters wanted 447 ; On Exit: 448 ; DX:AX = start of chain, 0 on failure 449 ; CY set on failure 450 ; 451 ; We want to allocate a chain of CX clusters, AX was previous cluster 452 ; We return with CY clear and AX = 1st cluster in chain on success, 453 ; CY set on failure 454 ; 455 ; When allocating a new chain we first ask SSTOR how much physical space is 456 ; present on the disk. Until SSTOR reports at least 2 clusters free we 457 ; repeatedly call DELWATCH to purge files and recover space. If DELWATCH is 458 ; unable to free space we return "disk full". 459 ; 460 ; When allocating a block we normally are normally given a target block to 461 ; start searching from. We allow DELWATCH to alter this value when it frees 462 ; space to optimise the search. 463 ; 0 0000A415 890E[0C00] mov [alloc_chain_cl],cx ; save entry parameters 0 0000A419 C706[0E00]0000 mov word [alloc_chain_cl+2],0 466 ; push ax ! push cx ; save entry parameters 0 0000A41F 52 push dx 0 0000A420 50 push ax ; save entry parameters 0 0000A421 E822FE call update_ddsc_free ; make sure DDSC_FREE is correct 470 %ifdef DELWATCH 471 alloc_chain10: 472 ; push dx ; DX = clusters wanted 0 0000A424 36C41E[0000] les bx,[ss:current_ddsc] 0 0000A429 A0[0000] mov al,[adrive] ; AL = current drive 0 0000A42C 833E[0000]00 cmp word [dosfat],FAT32 ; FAT32 drive? 0 0000A431 740C je alloc_chain12 ; yes 0 0000A433 268B4F1F mov cx,[es:DDSC_FREE + bx] ; CX = clusters available 0 0000A437 3B0E[0C00] cmp cx,[alloc_chain_cl] ; do we have enough room in the FAT ? 0 0000A43B 7238 jb alloc_chain20 ; if not ask DELWATCH to purge 0 0000A43D EB16 jmp alloc_chain15 481 alloc_chain12: 0 0000A43F 268B4F23 mov cx,word ptr [es:DDSC_BFREE+2 + bx] ; CX = clusters available 483 ; cmp cx,dx ; do we have enough room in the FAT ? 0 0000A443 3B0E[0E00] cmp cx,[alloc_chain_cl+2] ; do we have enough room in the FAT ? 0 0000A447 722C jb alloc_chain20 ; if not ask DELWATCH to purge 0 0000A449 770A ja alloc_chain15 0 0000A44B 268B4F21 mov cx,word ptr [es:DDSC_BFREE + bx] 0 0000A44F 3B0E[0C00] cmp cx,[alloc_chain_cl] 0 0000A453 7220 jb alloc_chain20 490 alloc_chain15: 0 0000A455 B410 mov ah,SSTOR_SPACE ; does Superstore have room for data? 0 0000A457 36FF1E[0000] call far [ss:fdos_stub] ; call stub routine 0 0000A45C 85C9 test cx,cx ; are we out of space ? 0 0000A45E 752A jnz alloc_chain40 ; no, go ahead and allocate the chain 0 0000A460 26894F1F mov [es:DDSC_FREE + bx],cx ; SSTOR says there's none, lets agree 0 0000A464 833E[0000]00 cmp word [dosfat],FAT32 ; FAT32 drive? 0 0000A469 7508 jne alloc_chain16 ; no, then skip 0 0000A46B 26894F21 mov word ptr [es:DDSC_BFREE + bx],cx ; SSTOR says there's none, lets agree 0 0000A46F 26894F23 mov word ptr [es:DDSC_BFREE+2 + bx],cx 500 alloc_chain16: 501 ; call update_fat ; flush FAT to bring SSTOR up to date 0 0000A473 EBAF jmp alloc_chain10 ; go round again and ask DELWATCH to 503 ; free up some more space 504 ; we loop until either SSTOR says OK 505 ; or DELWATCH frees all it can 506 alloc_chain20: 0 0000A475 268B4F1F mov cx,[es:DDSC_FREE + bx] 0 0000A479 B403 mov ah,DELW_FREECLU ; ask DELWATCH to purge a file 0 0000A47B 36FF1E[0000] call far [ss:fdos_stub] ; call stub routine 0 0000A480 263B4F1F cmp cx,[es:DDSC_FREE + bx] ; can DELWATCH free up any space ? 0 0000A484 759E jne alloc_chain10 ; yes, go and try again 512 alloc_chain30: 0 0000A486 58 pop ax ; failure, restore stack 0 0000A487 5A pop dx 0 0000A488 EB61 jmp alloc_chain80 ; and exit in failure 516 517 alloc_chain40: 518 %endif 0 0000A48A 58 pop ax ; restore entry parameters 0 0000A48B 5A pop dx 521 ; push cx ; save # required 522 ; xor dx,dx 0 0000A48C E86200 call allocate_cluster ; try to allocate 1st cluster 524 ; pop cx ; recover # required 0 0000A48F 85C0 test ax,ax ; could we ? 0 0000A491 7504 jnz alloc_chain45 0 0000A493 85D2 test dx,dx 0 0000A495 7454 jz alloc_chain80 529 alloc_chain45: 530 ; dec cx ; one less to allocate 0 0000A497 832E[0C00]01 sub word [alloc_chain_cl],1 ; one less to allocate 0 0000A49C 831E[0E00]00 sbb word [alloc_chain_cl+2],0 533 0 0000A4A1 52 push dx 0 0000A4A2 50 push ax ; save head of chain 536 ; jcxz alloc_chain60 0 0000A4A3 833E[0E00]00 cmp word [alloc_chain_cl+2],0 0 0000A4A8 7507 jnz alloc_chain50 0 0000A4AA 833E[0C00]00 cmp word [alloc_chain_cl],0 0 0000A4AF 7431 jz alloc_chain60 541 alloc_chain50: 542 ; push cx 543 0 0000A4B1 52 push dx 0 0000A4B2 50 push ax ; save current end of chain 0 0000A4B3 E83B00 call allocate_cluster ; allocate another cluster 0 0000A4B6 5B pop bx ; CX:BX = end of chain 0 0000A4B7 59 pop cx 549 0 0000A4B8 85C0 test ax,ax ; could we allocate anything ? 0 0000A4BA 7504 jnz alloc_chain55 0 0000A4BC 85D2 test dx,dx 0 0000A4BE 7426 jz alloc_chain70 ; no, bail out and free partial chain 554 555 alloc_chain55: 0 0000A4C0 93 xchg ax,bx ; DX:AX = previous cluster, link cluster 0 0000A4C1 87D1 xchg dx,cx 0 0000A4C3 51 push cx 0 0000A4C4 53 push bx ; CX:BX to end of the chain 0 0000A4C5 E8FB00 call fixfat 0 0000A4C8 58 pop ax ; DX:AX = new end of chain 0 0000A4C9 5A pop dx 563 564 ; pop cx 565 ; loop alloc_chain50 0 0000A4CA 832E[0C00]01 sub word [alloc_chain_cl],1 0 0000A4CF 831E[0E00]00 sbb word [alloc_chain_cl+2],0 0 0000A4D4 833E[0E00]00 cmp word [alloc_chain_cl+2],0 0 0000A4D9 75D6 jne alloc_chain50 0 0000A4DB 833E[0C00]00 cmp word [alloc_chain_cl],0 0 0000A4E0 75CF jne alloc_chain50 572 alloc_chain60: 0 0000A4E2 58 pop ax ; return the start of the chain as it's 0 0000A4E3 5A pop dx 0 0000A4E4 F8 clc ; long enough now... 0 0000A4E5 C3 ret 577 578 alloc_chain70: 579 ; We haven't enough free clusters - lets free what we allocated so far 580 ; pop cx ; discard count 0 0000A4E6 58 pop ax ; DX:AX = start of chain 0 0000A4E7 5A pop dx 0 0000A4E8 E89CFE call delfat ; release the chain 584 alloc_chain80: 0 0000A4EB 31C0 xor ax,ax 0 0000A4ED 31D2 xor dx,dx 0 0000A4EF F9 stc ; we couldn't manage it 0 0000A4F0 C3 ret 589 590 allocate_cluster: 591 ;---------------- 592 ; On Entry: 593 ; DX:AX = cluster to start from (0 = none known) 594 ; On Exit: 595 ; DX:AX = cluster allocated 596 ; 0 0000A4F1 85C0 test ax,ax ; previous block known? 0 0000A4F3 7520 jnz alloc_cl10 ; skip if it is 0 0000A4F5 85D2 test dx,dx 0 0000A4F7 751C jnz alloc_cl10 601 ; push ds 602 ; lds bx,ss:current_ddsc 603 ; mov ax,ds:DDSC_BLOCK[bx] ; else continue from last allocated block 0 0000A4F9 06 push es 0 0000A4FA 36C41E[0000] les bx,[ss:current_ddsc] 0 0000A4FF 268B471D mov ax,[es:DDSC_BLOCK + bx] ; else continue from last allocated block 0 0000A503 31D2 xor dx,dx 0 0000A505 833E[0000]00 cmp word [dosfat],FAT32 ; FAT32 drive? 0 0000A50A 7508 jne alloc_cl05 ; no, then skip 0 0000A50C 268B473B mov ax,word ptr [es:DDSC_BBLOCK + bx] ; else continue from last allocated block 0 0000A510 268B573D mov dx,word ptr [es:DDSC_BBLOCK+2 + bx] 612 alloc_cl05: 613 ; pop ds 0 0000A514 07 pop es 615 alloc_cl10: 0 0000A515 8B1E[0000] mov bx,[lastcl] ; highest block number on current disk 617 ; cmp ax,bx ; is it within disk size? 0 0000A519 3B16[0200] cmp dx,[blastcl+2] ; is it within disk size? 0 0000A51D 7708 ja alloc_cl15 0 0000A51F 720A jb alloc_cl20 0 0000A521 3B06[0000] cmp ax,[blastcl] 0 0000A525 7204 jb alloc_cl20 ; skip if it is 623 alloc_cl15: 0 0000A527 29C0 sub ax,ax ; start at the beginning 0 0000A529 29D2 sub dx,dx 626 627 alloc_cl20: 628 ; mov si,ax ; remember start of search 0 0000A52B A3[0800] mov [alloc_clus_cl],ax ; remember start of search 0 0000A52E 8916[0A00] mov [alloc_clus_cl+2],dx 0 0000A532 85C0 test ax,ax ; is this the 1st block? 0 0000A534 7505 jnz alloc_cl30 ; no 0 0000A536 85D2 test dx,dx 0 0000A538 7501 jnz alloc_cl30 0 0000A53A 40 inc ax ; start at beginning 636 alloc_cl30: ; main loop: 637 ; inc ax ; skip to block after current 0 0000A53B 83C001 add ax,1 ; skip to block after current 0 0000A53E 83D200 adc dx,0 0 0000A541 52 push dx 0 0000A542 50 push ax ; quick save 0 0000A543 E890FE call getblk ; get the content of this block 0 0000A546 58 pop ax 0 0000A547 5A pop dx 0 0000A548 743D jz alloc_cl50 ; return if free 646 ; cmp ax,bx ; are we at the end yet? 0 0000A54A 3B16[0200] cmp dx,[blastcl+2] ; are we at the end yet? 0 0000A54E 7708 ja alloc_cl35 ; yes 0 0000A550 72E9 jb alloc_cl30 ; no, try next block 0 0000A552 3B06[0000] cmp ax,[blastcl] 0 0000A556 72E3 jb alloc_cl30 652 alloc_cl35: 0 0000A558 31C0 xor ax,ax ; wrap to start of disk 0 0000A55A 31D2 xor dx,dx 655 ; mov bx,si ; remember starting position last time 0 0000A55C 8B1E[0A00] mov bx,[alloc_clus_cl+2] ; remember starting position last time 0 0000A560 85DB test bx,bx ; have we been all the way round ? 0 0000A562 75C7 jnz alloc_cl20 ; no, lets search from start 0 0000A564 8B1E[0800] mov bx,[alloc_clus_cl] 0 0000A568 85DB test bx,bx 0 0000A56A 75BF jnz alloc_cl20 662 ; push ds 663 ; lds bx,ss:current_ddsc 664 ; mov ds:DDSC_FREE[bx],ax ; we definitely have none left 0 0000A56C 06 push es 0 0000A56D 36C41E[0000] les bx,[ss:current_ddsc] 0 0000A572 2689471F mov [es:DDSC_FREE + bx],ax ; we definitely have none left 0 0000A576 833E[0000]00 cmp word [dosfat],FAT32 ; FAT32 drive? 0 0000A57B 7508 jne alloc_cl36 ; no, then skip 0 0000A57D 26894721 mov word ptr [es:DDSC_BFREE + bx],ax ; we definitely have none left 0 0000A581 26895723 mov word ptr [es:DDSC_BFREE+2 + bx],dx 672 alloc_cl36: 673 ; pop ds 0 0000A585 07 pop es 0 0000A586 C3 ret ; return (0); 676 677 alloc_cl50: 678 ; push ds ; block # AX is available 679 ; lds bx,ss:current_ddsc 680 ; mov ds:DDSC_BLOCK[bx],ax ; remember for next time 0 0000A587 06 push es ; block # AX is available 0 0000A588 36C41E[0000] les bx,[ss:current_ddsc] 0 0000A58D 2689471D mov [es:DDSC_BLOCK + bx],ax ; remember for next time 0 0000A591 833E[0000]00 cmp word [dosfat],FAT32 ; FAT32 drive? 0 0000A596 7508 jne alloc_cl52 ; no, then skip 0 0000A598 2689473B mov word ptr [es:DDSC_BBLOCK + bx],ax ; remember for next time 0 0000A59C 2689573D mov word ptr [es:DDSC_BBLOCK+2 + bx],dx 688 alloc_cl52: 689 ; pop ds 0 0000A5A0 07 pop es 691 0 0000A5A1 52 push dx 0 0000A5A2 50 push ax 0 0000A5A3 833E[0000]00 cmp word [dosfat],FAT32 ; FAT32 file system? 0 0000A5A8 7408 je alloc_cl55 ; yes, then handle this case specially 0 0000A5AA 8B1E[0000] mov bx,[dosfat] ; mark this block as end of file 0 0000A5AE 31C9 xor cx,cx 0 0000A5B0 EB05 jmp alloc_cl60 699 alloc_cl55: 0 0000A5B2 BBFFFF mov bx,FAT16 0 0000A5B5 89D9 mov cx,bx 702 alloc_cl60: 0 0000A5B7 E80900 call fixfat ; for convenience 0 0000A5BA 58 pop ax 0 0000A5BB 5A pop dx 706 0 0000A5BC 85C0 test ax,ax ; update ZF from AX 0 0000A5BE 7502 jnz alloc_cl65 0 0000A5C0 85D2 test dx,dx 710 alloc_cl65: 0 0000A5C2 C3 ret ; return block number 712 713 714 715 716 717 %ifdef DELWATCH 718 719 ; Update a FAT entry with a new value 720 721 change_fat_entry: 722 ;---------------- 723 ; On Entry: 724 ; DX:AX = block number to change 725 ; CX:BX = new value 726 ; On Exit: 727 ; None 728 ; 729 ; mov bx,dx 730 ; jmp fixfat 731 %endif 732 733 ; entry: DX:AX = block number to change 734 ; CX:BX = new value 735 ; exit: DS,ES = sysdat 736 737 ;------ 738 fixfat: 739 ;------ 0 0000A5C3 51 push cx ; save new value 0 0000A5C4 53 push bx 0 0000A5C5 52 push dx 0 0000A5C6 50 push ax 0 0000A5C7 E87CFC call update_ddsc_free ; make sure DDSC_FREE is correct 0 0000A5CA 58 pop ax 0 0000A5CB 5A pop dx 747 ; cmp dosfat,FAT16 ; check if 16-bit FAT 748 ; jne fixfat30 ; skip if 12 bit FAT 0 0000A5CC 813E[0000]FF0F cmp word [dosfat],FAT12 ; check if 16/32-bit FAT 0 0000A5D2 7503 jne fixfat04 ; skip if 12 bit FAT 0 0000A5D4 E98D00 jmp fixfat30 752 fixfat04: 0 0000A5D7 E81C01 call fatptr ; ES:BX -> FAT word to modify 0 0000A5DA 58 pop ax ; restore new value 0 0000A5DB 5A pop dx 0 0000A5DC 31FF xor di,di ; get a zero (no change of space) 0 0000A5DE 833E[0000]00 cmp word [dosfat],FAT32 ; check if 32-bit FAT 0 0000A5E3 7525 jne fixfat09 ; skip if 16-bit FAT 759 0 0000A5E5 85C0 test ax,ax ; are we setting to 0 or non-zero? 0 0000A5E7 7502 jnz fixfat05 0 0000A5E9 85D2 test dx,dx 763 fixfat05: 0 0000A5EB 268707 xchg ax,[es:bx] ; set the low word in the buffer 0 0000A5EE 26875702 xchg dx,[es:2 + bx] ; and the high word 0 0000A5F2 750B jnz fixfat08 ; skip if releasing block 0 0000A5F4 85C0 test ax,ax ; check if word was 0 before 0 0000A5F6 7504 jnz fixfat06 0 0000A5F8 85D2 test dx,dx 0 0000A5FA 745C jz fixfat20 ; skip if setting 0 to 0 771 fixfat06: 0 0000A5FC 47 inc di ; DI = 0001h, one free cluster more 0 0000A5FD EB1E jmp fixfat15 774 fixfat08: ; allocating or fixing block 0 0000A5FF 85C0 test ax,ax ; check if word was 0 before 0 0000A601 7555 jnz fixfat20 ; skip if setting non-0 to non-0 0 0000A603 85D2 test dx,dx 0 0000A605 7551 jnz fixfat20 0 0000A607 4F dec di ; one free cluster less now 0 0000A608 EB13 jmp fixfat15 781 782 fixfat09: 0 0000A60A 85C0 test ax,ax ; are we setting to 0 or non-zero? 0 0000A60C 268707 xchg ax,[es:bx] ; set the word in the buffer 0 0000A60F 7507 jnz fixfat10 ; skip if releasing block 0 0000A611 85C0 test ax,ax ; check if word was 0 before 0 0000A613 7443 jz fixfat20 ; skip if setting 0 to 0 0 0000A615 47 inc di ; DI = 0001h, one free cluster more 0 0000A616 EB05 jmp fixfat15 790 fixfat10: ; allocating or fixing block 0 0000A618 85C0 test ax,ax ; check if word was 0 before 0 0000A61A 753C jnz fixfat20 ; skip if setting non-0 to non-0 0 0000A61C 4F dec di ; one free cluster less now 794 795 fixfat15: ; DI = change in free space (-1,1) 0 0000A61D C436[0000] les si,[current_ddsc] 0 0000A621 26017C1F add [es:DDSC_FREE + si],di ; update free space count 0 0000A625 833E[0000]00 cmp word [dosfat],FAT32 ; FAT32 drive? 0 0000A62A 752C jne fixfat20 ; no, then skip 0 0000A62C 83FFFF cmp di,0ffffh 0 0000A62F 740B je fixfat16 0 0000A631 26017C21 add word ptr [es:DDSC_BFREE + si],di ; update free space count 0 0000A635 2683542300 adc word ptr [es:DDSC_BFREE+2 + si],0 0 0000A63A EB0A jmp fixfat17 805 fixfat16: 0 0000A63C 26836C2101 sub word ptr [es:DDSC_BFREE + si],1 ; update free space count 0 0000A641 26835C2300 sbb word ptr [es:DDSC_BFREE+2 + si],0 808 fixfat17: 0 0000A646 268B4421 mov ax,word ptr [es:DDSC_BFREE + si] 0 0000A64A 26837C2300 cmp word ptr [es:DDSC_BFREE+2 + si],0 ; does this fit into 16 bits? 0 0000A64F 7403 je fixfat18 ; yes, proceed 0 0000A651 B8FEFF mov ax,0fffeh ; else use a fake 16-bit value 813 fixfat18: 0 0000A654 2689441F mov [es:DDSC_FREE + si],ax 815 fixfat20: 0 0000A658 C436[0000] les si,[bcb_root] ; ES:SI -> buffer control block 0 0000A65C 26804C0540 or byte [es:BCB_FLAGS + si],BF_DIRTY 818 ; mark the buffer as dirty 0 0000A661 1E push ds 0 0000A662 07 pop es ; ES back to local DS 0 0000A663 C3 ret 822 823 824 ; We're dealing with a 12-bit FAT... 825 826 fixfat30: ; changing 12-bit FAT entry 0 0000A664 31D2 xor dx,dx 0 0000A666 E88D00 call fatptr ; get address of block AX in ES:BX 0 0000A669 59 pop cx ; get new value 0 0000A66A 5A pop dx ; got 16-bit value from stack, clean up 0 0000A66B 268B17 mov dx,[es:bx] ; get old value 0 0000A66E 740D jz fixfat40 ; skip if even word 0 0000A670 B8F0FF mov ax,0FFF0h ; set mask for new value 0 0000A673 01C9 add cx,cx ; else shift new value into top bits 0 0000A675 01C9 add cx,cx 0 0000A677 01C9 add cx,cx 0 0000A679 01C9 add cx,cx 0 0000A67B EB05 jmp fixfat50 ; set the new word 839 fixfat40: 0 0000A67D B8FF0F mov ax,00FFFh ; set mask for new value 0 0000A680 21C1 and cx,ax 842 fixfat50: ; AX = mask, CX = new, DX = old 0 0000A682 BE0000 mov si,0 ; assume space doesn't change 0 0000A685 7507 jnz fixfat60 ; skip if new value is zero 0 0000A687 85C2 test dx,ax ; test if old value was zero as well 0 0000A689 7408 jz fixfat70 ; yes, no change in free space 0 0000A68B 46 inc si ; else one more block available 0 0000A68C EB05 jmp fixfat70 849 fixfat60: ; new value is non-zero 0 0000A68E 85C2 test dx,ax ; is old value non-zero as well? 0 0000A690 7501 jnz fixfat70 ; yes, no change in free space 0 0000A692 4E dec si ; else one block less free now 853 fixfat70: 0 0000A693 F7D0 not ax ; flip the mask bits around 0 0000A695 21C2 and dx,ax ; zero out old value 0 0000A697 09CA or dx,cx ; combine old & new value 0 0000A699 268917 mov [es:bx],dx ; update the FAT 0 0000A69C 96 xchg ax,si ; AX = free space change (-1, 0 , 1) 0 0000A69D C436[0000] les si,[current_ddsc] 0 0000A6A1 2601441F add [es:DDSC_FREE + si],ax ; update free space count 861 ; add es:word ptr DDSC_BFREE[si],ax ; update free space count (32-bit) 862 ; adc es:word ptr DDSC_BFREE+2[si],0 0 0000A6A5 C436[0000] les si,[bcb_root] ; get buffer control block 0 0000A6A9 26804C0540 or byte [es:BCB_FLAGS + si],BF_DIRTY 865 ; mark the buffer as dirty 0 0000A6AE 803E[0600]00 cmp byte [split_fat],0 ; is 12-bit entry split across sectors 0 0000A6B3 7437 je fixfat80 ; need some magic if so 868 ; handle a split FAT update 0 0000A6B5 8B16[0000] mov dx,[fatrec] ; lower sector number 0 0000A6B9 A1[0200] mov ax,[fatrec+2] 871 ; inc dx ; get the upper sector 0 0000A6BC 83C201 add dx,1 ; get the upper sector 0 0000A6BF 83D000 adc ax,word ptr 0 0 0000A6C2 E8F800 call locate_fat ; find the buffer 0 0000A6C5 26804C0540 or byte [es:BCB_FLAGS + si],BF_DIRTY 876 ; mark buffer as write pending 0 0000A6CA A0[0500] mov al,[fatbyth] ; get the high byte 0 0000A6CD 26884414 mov [es:BCB_DATA + si],al ; store the high byte at the beginning 0 0000A6D1 8B16[0000] mov dx,[fatrec] ; get the previous sector 0 0000A6D5 A1[0200] mov ax,[fatrec+2] 0 0000A6D8 E8E200 call locate_fat ; read into memory 0 0000A6DB 26804C0540 or byte [es:BCB_FLAGS + si],BF_DIRTY 883 ; mark buffer as write pending 0 0000A6E0 8B1E[0000] mov bx,[psecsiz] 0 0000A6E4 4B dec bx ; BX = sector size - 1 0 0000A6E5 A0[0400] mov al,[fatbytl] ; get the low byte 0 0000A6E8 26884014 mov [es:BCB_DATA + si+bx],al 888 889 fixfat80: 0 0000A6EC 1E push ds 0 0000A6ED 07 pop es ; ES back to local DS 0 0000A6EE C3 ret 893 894 895 ; On Entry: 896 ; DX:AX = cluster number 897 ; On Exit: 898 ; DX:AX preserved 899 ; ES:BX -> address of word 900 ; BCBSEG = segment of FAT FCB 901 ; ZF = 1 if word on even address 902 ; SPLIT_FAT = 0FFh if xing sector boundary 903 ; 904 ; CX = entries left in sector (if FAT16 - performance optimisation) 905 ; 906 907 Public fatptr_tag 908 fatptr_tag: 0 0000A6EF C606[0700]01 mov byte [tag_flg],1 ; do not actually read FAT, just tag it 0 0000A6F4 EB05 jmp fatptr05 911 912 Public fatptr 913 fatptr: 914 ;------ 0 0000A6F6 C606[0700]00 mov byte [tag_flg],0 ; normal operation 916 fatptr05: 0 0000A6FB 52 push dx ; save block number 0 0000A6FC 50 push ax 919 ; mov bx,ax 920 ; sub dx,dx ; AX/DX = cluster # 0 0000A6FD 813E[0000]FF0F cmp word [dosfat],FAT12 ; is it 12 bit FAT? 0 0000A703 7411 je fatptr09 0 0000A705 D1E0 shl ax,1 ; * 2 0 0000A707 D1D2 rcl dx,1 0 0000A709 833E[0000]00 cmp word [dosfat],FAT32 ; is it 32 bit FAT? 0 0000A70E 750F jne fatptr10 ; no, then it must be FAT16 0 0000A710 D1E0 shl ax,1 ; * 2 again, making it * 4 in total 0 0000A712 D1D2 rcl dx,1 0 0000A714 EB09 jmp fatptr10 930 fatptr09: 0 0000A716 89C3 mov bx,ax ; * 1.5 0 0000A718 D1E8 shr ax,1 ; shift for 1 1/2 byte, else 2 byte 0 0000A71A 01D8 add ax,bx 0 0000A71C 83D200 adc dx,0 935 fatptr10: 936 ; add ax,bx ; AX = offset into FAT 937 ; adc dx,0 ; AX/DX = 32 bit offset 0 0000A71F 8B0E[0000] mov cx,[psecsiz] ; CX = sector size 0 0000A723 51 push cx 940 ; div cx ; AX = sector offset 0 0000A724 52 push dx 0 0000A725 50 push ax 0 0000A726 31DB xor bx,bx 0 0000A728 53 push bx 0 0000A729 51 push cx 0 0000A72A 83EC08 sub sp,8 ; reserve space for result on stack 0 0000A72D E8[0000] call div32 0 0000A730 5B pop bx 0 0000A731 83C402 add sp,2 0 0000A734 58 pop ax 0 0000A735 5A pop dx 0 0000A736 83C408 add sp,8 ; clean up the stack 0 0000A739 59 pop cx 0 0000A73A 49 dec cx ; CX = sector size - 1 955 ; push dx ; DX = offset within FAT sector 0 0000A73B 53 push bx ; BX = offset within FAT sector 0 0000A73C 51 push cx 0 0000A73D 0306[0000] add ax,[fatadd] ; make it absolute sector address 0 0000A741 83D200 adc dx,0 0 0000A744 A3[0000] mov [fatrec],ax ; save FAT sector for FIXFAT 0 0000A747 8916[0200] mov [fatrec+2],dx 0 0000A74B 92 xchg ax,dx ; AX:DX = FAT sector 0 0000A74C F606[0700]01 test byte [tag_flg],1 ; tag mode requested? 0 0000A751 7405 jz fatptr15 ; no, locate the sector normally 0 0000A753 E86300 call tag_fat ; else tag the buffer if it exists 0 0000A756 EB03 jmp fatptr16 967 fatptr15: 0 0000A758 E86200 call locate_fat ; locate the sector 969 fatptr16: 0 0000A75B 59 pop cx ; CX = sector size - 1 0 0000A75C 5B pop bx ; restore offset within FAT sector 0 0000A75D 58 pop ax ; restore cluster # 0 0000A75E 5A pop dx 0 0000A75F 29D9 sub cx,bx ; CX = bytes left in sector - 1 0 0000A761 8D5814 lea bx,[BCB_DATA + si+bx] ; ES:BX -> buffer data 976 ; cmp dosfat,FAT16 ; is it 16 bit media 977 ; jne fatptr20 ; skip if 12 bit media 0 0000A764 813E[0000]FF0F cmp word [dosfat],FAT12 ; is it 16 bit media 0 0000A76A 7405 je fatptr20 ; skip if 12 bit media 0 0000A76C D1E9 shr cx,1 ; CX = extra entries left in sector 0 0000A76E 39C0 cmp ax,ax ; always set ZF = 1 0 0000A770 C3 ret ; return ES:BX -> word in FAT 983 984 fatptr20: ; it's a 12 bit FAT, is it a split FAT? 0 0000A771 C606[0600]00 mov byte [split_fat],0 ; assume no boundary crossing 0 0000A776 E303 jcxz fatptr30 ; end of sector, it's a split FAT 0 0000A778 A801 test al,1 ; ZF = 1 if even cluster 0 0000A77A C3 ret ; return ES:BX -> word in FAT buffer 989 990 fatptr30: ; block split across two sectors 0 0000A77B 52 push dx 0 0000A77C 50 push ax 0 0000A77D C606[0600]FF mov byte [split_fat],0FFh ; yes, the difficult case 0 0000A782 268A07 mov al,[es:bx] ; get the low byte from 1st sector 0 0000A785 A2[0400] mov [fatbytl],al ; save it for later 0 0000A788 8B16[0000] mov dx,[fatrec] ; get the FAT record is 0 0000A78C A1[0200] mov ax,[fatrec+2] 998 ; inc dx ; get 2nd sector 0 0000A78F 83C201 add dx,1 ; get 2nd sector 0 0000A792 83D000 adc ax,word ptr 0 0 0000A795 F606[0700]01 test byte [tag_flg],1 ; tag mode requested? 0 0000A79A 7405 jz fatptr35 ; no, locate the sector normally 0 0000A79C E81A00 call tag_fat ; else tag the buffer if it exists 0 0000A79F EB03 jmp fatptr36 1005 fatptr35: 0 0000A7A1 E81900 call locate_fat ; read the 2nd sector 1007 fatptr36: 0 0000A7A4 29DB sub bx,bx 0 0000A7A6 8D5814 lea bx,[BCB_DATA + si+bx] ; ES:BX -> buffer data 0 0000A7A9 268A07 mov al,[es:bx] ; get 1st byte from next sector 0 0000A7AC A2[0500] mov [fatbyth],al ; save the high byte 0 0000A7AF 1E push ds ; ES = local DS 0 0000A7B0 07 pop es 0 0000A7B1 BB[0400] mov bx,offset fatbytl ; ES:BX -> 0 0000A7B4 58 pop ax 0 0000A7B5 5A pop dx 0 0000A7B6 A801 test al,1 ; set non-zero condition, odd word 0 0000A7B8 C3 ret 1019 1020 1021 ; entry: AX:DX = sector number to read 1022 ; exit: ES:SI = BCB 1023 1024 tag_fat: 0 0000A7B9 31C9 xor cx,cx ; do not read the buffer, just tag it 0 0000A7BB EB03 jmp locate_buffer 1027 1028 locate_fat: 1029 ;---------- 1030 ; mov ah,0 ; set sector address overflow = 0 1031 ; mov ax,0 ; set sector address overflow = 0 0 0000A7BD B902FF mov cx,0ff00h+BF_ISFAT ; request a FAT buffer w/ preread 1033 locate_buffer: 1034 ;------------- 1035 ; On Entry: 1036 ; AX:DX = sector to locate 1037 ; adrive = driver 1038 ; CH = 0FFh if preread required 1039 ; CL = buffer type, 0 means tag only 1040 ; On Exit: 1041 ; ES:SI -> BCB_ 1042 ; 1043 1044 ; mov al,adrive ; get our drive number 0 0000A7C0 8A1E[0000] mov bl,[adrive] ; get our drive number 0 0000A7C4 C436[0000] les si,[bcb_root] ; get it from the right buffer list 1047 locate10: 0 0000A7C8 263B5406 cmp dx,[es:BCB_REC + si] ; does our sector address match? 0 0000A7CC 750C jne locate20 ; skip if it doesn't 1050 ; cmp ah,es:byte ptr BCB_REC2[si] ; does record address overflow match? 0 0000A7CE 263B4408 cmp ax,[es:BCB_REC2 + si] ; does record address overflow match? 0 0000A7D2 7506 jne locate20 ; skip if not 1053 ; cmp al,es:BCB_DRV[si] ; does the drive match? 0 0000A7D4 263A5C04 cmp bl,[es:BCB_DRV + si] ; does the drive match? 0 0000A7D8 7432 je locate30 ; found if it all matches 1056 locate20: ; MRU buffer doesn't match 0 0000A7DA 268B34 mov si,[es:BCB_NEXT + si] ; try the next 0 0000A7DD 3B36[0000] cmp si,word ptr [bcb_root] ; while there are more buffers 0 0000A7E1 75E5 jne locate10 1060 0 0000A7E3 80F900 cmp cl,0 ; shall we only tag an existing buffer? 0 0000A7E6 744F je locate50 ; yes, then do not sacrifice this one 0 0000A7E8 50 push ax 0 0000A7E9 51 push cx 0 0000A7EA 52 push dx ; save all registers 0 0000A7EB 268B7402 mov si,[es:BCB_PREV + si] ; recycle least recently used buffer 0 0000A7EF E8B800 call flush_buffer ; write buffer to disk 0 0000A7F2 5A pop dx 0 0000A7F3 59 pop cx 0 0000A7F4 58 pop ax ; restore all registers 1071 1072 ; mov es:BCB_DRV[si],al ; fill in the BCB: drive 0 0000A7F5 26885C04 mov [es:BCB_DRV + si],bl ; fill in the BCB: drive 0 0000A7F9 26895406 mov [es:BCB_REC + si],dx ; record low 1075 ; mov es:byte ptr BCB_REC2[si],ah ; record high 0 0000A7FD 26894408 mov [es:BCB_REC2 + si],ax ; record high 0 0000A801 26884C05 mov [es:BCB_FLAGS + si],cl ; mark as clean, ISFAT,ISDIR or ISDAT 0 0000A805 84ED test ch,ch ; is preread required? 0 0000A807 7403 jz locate30 ; skip if it isn't 0 0000A809 E84501 call fill_buffer ; read it from disk 1081 locate30: 0 0000A80C 3B36[0000] cmp si,word ptr [bcb_root] ; are we already at the head ? 0 0000A810 7501 jne locate40 ; if not move ourself there 0 0000A812 C3 ret 1085 locate40: 0 0000A813 268B1C mov bx,[es:BCB_NEXT + si] ; BX = next buffer 0 0000A816 268B7C02 mov di,[es:BCB_PREV + si] ; DI = previous buffer 0 0000A81A 26891D mov [es:BCB_NEXT + di],bx ; unlink buffer from the 0 0000A81D 26897F02 mov [es:BCB_PREV + bx],di ; chain 0 0000A821 89F3 mov bx,si 0 0000A823 871E[0000] xchg bx,word ptr [bcb_root] ; become the new head, BX = old head 0 0000A827 26891C mov [es:BCB_NEXT + si],bx ; old chain follow us 0 0000A82A 89F7 mov di,si 0 0000A82C 26877F02 xchg di,[es:BCB_PREV + bx] ; back link to our buffer, DI = LRU buffer 0 0000A830 26897C02 mov [es:BCB_PREV + si],di ; link ourselves to LRU buffer 0 0000A834 268935 mov [es:BCB_NEXT + di],si ; forward link to our buffer 1097 locate50: 0 0000A837 C3 ret 1099 1100 1101 ; Flush all dirty FAT buffers for drive AL 1102 ; entry: AL = drive to flush (0-15) 1103 ; exit: CY = 0 if no error 1104 ; ax,bx,cx,dx,es preserved 1105 1106 flush_fat: 1107 ;--------- 1108 ; entry: AL = drive for FAT flush 1109 0 0000A838 B402 mov ah,BF_ISFAT ; flush all dirty FAT buffers 0 0000A83A EB22 jmp flush_drive ; shared code for all flushes 1112 1113 ;---------- 1114 update_dir: 1115 ;---------- 0 0000A83C E8[0000] call flush_dirbuf ; flush local dirbuf to buffers 1117 ;--------- 1118 flush_dir: 1119 ;--------- 0 0000A83F B404 mov ah,BF_ISDIR ; write out dirty directories 0 0000A841 EB18 jmp flush_adrive ; update the disk 1122 1123 1124 ;---------- 1125 update_dat: 1126 ;---------- 0 0000A843 B408 mov ah,BF_ISDAT ; write out dirty data 0 0000A845 EB14 jmp flush_adrive ; update the disk 1129 1130 ;---------- 1131 update_fat: ;write out modified FAT buffers 1132 ;---------- 0 0000A847 06 push es 0 0000A848 53 push bx 0 0000A849 C41E[0000] les bx,[current_ddsc] 0 0000A84D 26837F27FF cmp word [es:DDSC_FSINFO + bx],0ffffh;FS info sector present? 0 0000A852 7403 je update_fat10 ; no, then do not to write it, either 0 0000A854 E82802 call write_fsinfo ; update fs info block if applicable 1139 update_fat10: 0 0000A857 5B pop bx 0 0000A858 07 pop es 0 0000A859 B402 mov ah,BF_ISFAT ; flush all dirty FAT buffers 1143 ; jmp flush_adrive ; update the disk if dirty 1144 1145 flush_adrive: 1146 ;------------ 0 0000A85B A0[0000] mov al,[adrive] ; AL = currently selected drive 1148 ; jmp flush_drive 1149 1150 ; Write out all dirty data buffers for a given drive 1151 ; entry: AL = drive to be flushed 1152 ; AH = mask of buffer types to be flushed 1153 ; exit: AX,DX preserved 1154 ; Note: sector buffers will be written in the 1155 ; sequence in which they appear on disk (low to high) 1156 1157 flush_drive: 1158 ;----------- 0 0000A85E 06 push es 0 0000A85F 56 push si 1161 flush_drive10: 0 0000A860 C436[0000] les si,[bcb_root] ; start with the first buffer 0 0000A864 BBFFFF mov bx,0FFFFh ; assume no buffer found 1164 flush_drive20: 0 0000A867 26F6440540 test byte [es:BCB_FLAGS + si],BF_DIRTY 1166 ; has buffer been written to? 0 0000A86C 7423 jz flush_drive40 ; no, do the next one 0 0000A86E 26846405 test [es:BCB_FLAGS + si],ah ; is it one of these buffers? 0 0000A872 741D jz flush_drive40 ; no, do the next one 0 0000A874 263A4404 cmp al,[es:BCB_DRV + si] ; does the drive match? 0 0000A878 7517 jne flush_drive40 ; skip if wrong drive 1172 ; we've found a buffer to flush 0 0000A87A 83FBFF cmp bx,0FFFFh ; first buffer ever found in list? 0 0000A87D 7410 jz flush_drive30 ; yes, save as new best candidate 1175 ; else check if < previous lowest addr 0 0000A87F 268B5406 mov dx,[es:BCB_REC + si] 0 0000A883 2B5706 sub dx,[BCB_REC + bx] 1178 ; mov dl,es:byte ptr BCB_REC2[si] ; compare the disk addresss 1179 ; sbb dl,ds:byte ptr BCB_REC2[bx] 0 0000A886 268B5408 mov dx,[es:BCB_REC2 + si] ; compare the disk addresss 0 0000A88A 1B5708 sbb dx,[BCB_REC2 + bx] 0 0000A88D 7302 jnb flush_drive40 ; CY = 0 if new BCB higher 1183 flush_drive30: ; else ES = best BCB so far 0 0000A88F 89F3 mov bx,si ; save it for later 1185 flush_drive40: 0 0000A891 268B34 mov si,[es:BCB_NEXT + si] ; get next buffer address 0 0000A894 363B36[0000] cmp si,word ptr [ss:bcb_root] 0 0000A899 75CC jne flush_drive20 0 0000A89B 83FBFF cmp bx,0FFFFh ; did we find a dirty buffer? 0 0000A89E 7407 jz flush_drive50 ; no, all buffers cleaned 0 0000A8A0 89DE mov si,bx ; ES:SI -> BCB to flush 0 0000A8A2 E80500 call flush_buffer ; write sector to disk 0 0000A8A5 EBB9 jmp flush_drive10 ; check if more dirty buffers 1194 flush_drive50: 0 0000A8A7 5E pop si 0 0000A8A8 07 pop es 0 0000A8A9 C3 ret 1198 1199 flush_buffer: 1200 ;------------ 1201 ; entry: ES:SI = address of BCB 1202 ; exit: buffer flushed if BCB_FLAGS & BF_DIRTY 1203 1204 ; note: preserves AX,BX,CX,DX,ES 1205 0 0000A8AA 26F6440540 test byte [es:BCB_FLAGS + si],BF_DIRTY 1207 ; is the buffer dirty? 0 0000A8AF 746C jz flush_buf9 ; skip update if not modified 1209 flush_buf1: 0 0000A8B1 06 push es 0 0000A8B2 56 push si 0 0000A8B3 50 push ax 0 0000A8B4 53 push bx ; else save all registers 0 0000A8B5 51 push cx 0 0000A8B6 52 push dx 0 0000A8B7 268A4404 mov al,[es:BCB_DRV + si] ; get the buffer drive 0 0000A8BB 3A06[0000] cmp al,[adrive] ; same as the selected drive? 0 0000A8BF 740B je flush_buf2 ; skip if already selected 0 0000A8C1 06 push es ; save the BCB 0 0000A8C2 56 push si 0 0000A8C3 1E push ds 0 0000A8C4 07 pop es ; ES = SYSDAT 0 0000A8C5 E8[0000] call select_adrive ; select drive AL, ZF = 1 if logged in 0 0000A8C8 5E pop si 0 0000A8C9 07 pop es ; recover BCB 0 0000A8CA 7238 jc flush_buf5 ; don't flush to bad drive 1227 flush_buf2: 0 0000A8CC 8B0E[0000] mov cx,[nfats] ; else FAT sectors written CX times 0 0000A8D0 B003 mov al,00000011b ; mark as FAT write 0 0000A8D2 26F6440502 test byte [es:BCB_FLAGS + si],BF_ISFAT 0 0000A8D7 750E jnz flush_buf3 ; go ahead 0 0000A8D9 B90100 mov cx,1 ; directory/data written once only 0 0000A8DC B005 mov al,00000101b ; mark as directory write 0 0000A8DE 26F6440504 test byte [es:BCB_FLAGS + si],BF_ISDIR 0 0000A8E3 7502 jnz flush_buf3 ; if not dir, must be data 0 0000A8E5 B007 mov al,00000111b ; mark as data buffer write 1237 flush_buf3: ; CX = # of times to write sector 0 0000A8E7 A2[0000] mov [rwmode],al 0 0000A8EA 29C0 sub ax,ax ; offset for write = 0 0 0000A8EC 29D2 sub dx,dx 1241 flush_buf4: ; loop back to here for other copies 0 0000A8EE 52 push dx 0 0000A8EF 50 push ax 0 0000A8F0 51 push cx ; save loop variables 0 0000A8F1 E83201 call setup_rwx ; compute disk address 0 0000A8F4 E8F400 call write_buff ; write the sector 0 0000A8F7 59 pop cx 0 0000A8F8 58 pop ax 0 0000A8F9 5A pop dx 0 0000A8FA 0306[0000] add ax,[nfatrecs] ; move to next FAT copy 0 0000A8FE 1316[0200] adc dx,[nfatrecs+2] 0 0000A902 E2EA loop flush_buf4 ; repeat for all FAT copies 1253 flush_buf5: 0 0000A904 26806405BF and byte [es:BCB_FLAGS + si],~ BF_DIRTY 1255 ; mark it as no longer dirty 0 0000A909 A0[0000] mov al,[physical_drv] ; work drive for BDOS function 0 0000A90C 3A06[0000] cmp al,[adrive] ; drive from last IO_SELDSK 0 0000A910 7405 je flush_buf6 ; skip if flush to work drive 1259 ; else reselect BDOS drive after flush 0 0000A912 1E push ds 0 0000A913 07 pop es ; ES = SYSDAT 0 0000A914 E8[0000] call select_adrive ; reselect the work drive 1263 flush_buf6: 0 0000A917 5A pop dx 0 0000A918 59 pop cx ; restore all registers 0 0000A919 5B pop bx 0 0000A91A 58 pop ax 0 0000A91B 5E pop si 0 0000A91C 07 pop es 1270 flush_buf9: ; all done, CY = 0 if O.K. 0 0000A91D C3 ret 1272 1273 1274 ;------- 1275 zeroblk: ; DX:AX = blk 1276 ;------- 0 0000A91E 31DB xor bx,bx ; Start at begining of cluster 0 0000A920 31C9 xor cx,cx 0 0000A922 E8[0000] call clus2sec ; translate to sector address 0 0000A925 92 xchg ax,dx ; AX:DX = 32 bit sector address 1281 ; mov ah,al ; AH:DX = 24 bit sector address 0 0000A926 8B0E[0000] mov cx,[secperclu] ; CX == sectors/cluster 1283 zeroblk10: ; repeat for all sectors in cluster 0 0000A92A 50 push ax 0 0000A92B 51 push cx 0 0000A92C 52 push dx 0 0000A92D B90400 mov cx,BF_ISDIR ; locate directory sector w/o preread 0 0000A930 E88DFE call locate_buffer ; this will find the cheapest buffer 0 0000A933 26804C0540 or byte [es:BCB_FLAGS + si],BF_DIRTY 0 0000A938 8D7C14 lea di,[BCB_DATA + si] ; ES:DI -> disk buffer 0 0000A93B 8B0E[0000] mov cx,[psecsiz] ; CX = byte count for REP STOSB 0 0000A93F 31C0 xor ax,ax 0 0000A941 F3AA rep stosb ; zero the whole data buffer 0 0000A943 5A pop dx 0 0000A944 59 pop cx 0 0000A945 58 pop ax 0 0000A946 83C201 add dx,1 ; onto the next block 1298 ; adc ah,0 0 0000A949 83D000 adc ax,0 0 0000A94C E2DC loop zeroblk10 ; repeat for all sectors in cluster 0 0000A94E E9EEFE jmp flush_dir 1302 1303 1304 1305 1306 fill_buffer: 1307 ;----------- 1308 ; On Entry: 1309 ; ES:SI = address of BCB to be filled 1310 ; On Exit: 1311 ; ES:SI preserved 1312 ; data read into buffer 1313 ; 0 0000A951 26F6440502 test byte [es:BCB_FLAGS + si],BF_ISFAT 1315 ; are we reading a FAT sector? 0 0000A956 7407 jz fill_buf1 ; skip if directory/data 1317 ; mov al,es:BCB_DRV[si] ; get the drive 1318 ; call flush_fat ; write out all dirty buffers 0 0000A958 E84FFF call flush_buffer ; write out buffer if dirty 0 0000A95B B002 mov al,00000010b ; reading from FAT area 0 0000A95D EB0B jmp fill_buf3 ; go ahead 1322 fill_buf1: 0 0000A95F B004 mov al,00000100b ; else mark as directory 0 0000A961 26F6440504 test byte [es:BCB_FLAGS + si],BF_ISDIR; test if directory read 0 0000A966 7502 jnz fill_buf3 ; go ahead 1326 fill_buf2: ; neither FAT nor directory => data 0 0000A968 B006 mov al,00000110b ; mark read as data buffer read 1328 fill_buf3: 0 0000A96A A2[0000] mov [rwmode],al 0 0000A96D 51 push cx 0 0000A96E 31C9 xor cx,cx 0 0000A970 3C02 cmp al,00000010b 0 0000A972 7505 jne fill_buf4 0 0000A974 8B0E[0000] mov cx,[nfats] 0 0000A978 49 dec cx 1336 fill_buf4: 0 0000A979 26C64404FF mov byte [es:BCB_DRV + si],0FFh ; discard in case of error 0 0000A97E 29C0 sub ax,ax ; no offset for 2nd copy yet 0 0000A980 29D2 sub dx,dx 1340 fill_buf5: 0 0000A982 52 push dx 0 0000A983 50 push ax 0 0000A984 E89F00 call setup_rwx ; compute disk address 0 0000A987 E81800 call read_buff ; read the sector 0 0000A98A 58 pop ax 0 0000A98B 5A pop dx 0 0000A98C 790B jns fill_buf6 1348 ; we can end here only if CX was non-zero above and we failed to read a 1349 ; FAT copy while there is still another one we could use 0 0000A98E 0306[0000] add ax,[nfatrecs] 0 0000A992 1316[0200] adc dx,[nfatrecs+2] 0 0000A996 49 dec cx 0 0000A997 EBE9 jmp fill_buf5 1354 fill_buf6: 0 0000A999 59 pop cx 0 0000A99A A0[0000] mov al,[adrive] ; restore the drive 0 0000A99D 26884404 mov [es:BCB_DRV + si],al ; set the drive # 0 0000A9A1 C3 ret 1359 1360 read_buff: 1361 ;--------- 0 0000A9A2 06 push es 0 0000A9A3 56 push si ; save BCB_ 0 0000A9A4 FF36[0000] push word [cur_dma_seg] 0 0000A9A8 FF36[0000] push word [cur_dma] ; save DMA address 0 0000A9AC 51 push cx 0 0000A9AD 368B0E[0000] mov cx,[ss:deblock_seg] 0 0000A9B2 E30A jcxz read_buff10 0 0000A9B4 890E[0000] mov [cur_dma_seg],cx 0 0000A9B8 C706[0000]0000 mov word [cur_dma],0 ; xfer via deblocking buffer 1371 read_buff10: 0 0000A9BE 59 pop cx 0 0000A9BF E8[0000] call read_block 0 0000A9C2 8F06[0000] pop word [cur_dma] ; restore DMA address 0 0000A9C6 8F06[0000] pop word [cur_dma_seg] 0 0000A9CA 781C js read_buff20 ; can happen only on FAT read 0 0000A9CC 368B0E[0000] mov cx,[ss:deblock_seg] ; if deblocked, copy data 0 0000A9D1 E315 jcxz read_buff20 0 0000A9D3 C43E[0000] les di,[cur_dma] ; point to destination 0 0000A9D7 8B0E[0000] mov cx,[psecsiz] ; CX = sector size 0 0000A9DB D1E9 shr cx,1 ; CX = words per sector 0 0000A9DD 1E push ds 0 0000A9DE 368E1E[0000] mov ds,[ss:deblock_seg] 0 0000A9E3 31F6 xor si,si ; DS:SI = source 0 0000A9E5 F3A5 rep movsw ; copy the data 0 0000A9E7 1F pop ds 1387 read_buff20: ; SF still indicating error here 0 0000A9E8 5E pop si ; recover BCB_ 0 0000A9E9 07 pop es 0 0000A9EA C3 ret 1391 1392 write_buff: 1393 ;---------- 0 0000A9EB 06 push es 0 0000A9EC 56 push si 0 0000A9ED FF36[0000] push word [cur_dma_seg] 0 0000A9F1 FF36[0000] push word [cur_dma] 0 0000A9F5 368B0E[0000] mov cx,[ss:deblock_seg] ; if deblocking we have to 0 0000A9FA E31C jcxz write_buff10 ; copy the data first 0 0000A9FC 1E push ds ; save SYSDAT 0 0000A9FD C436[0000] les si,[cur_dma] ; ES:SI -> source 0 0000AA01 06 push es ; save source seg 0 0000AA02 8EC1 mov es,cx 0 0000AA04 31FF xor di,di ; ES:DI -> deblocking buffer 0 0000AA06 8C06[0000] mov [cur_dma_seg],es 0 0000AA0A 893E[0000] mov [cur_dma],di ; do xfer via deblocking buffer 0 0000AA0E 8B0E[0000] mov cx,[psecsiz] ; CX = sector size 0 0000AA12 D1E9 shr cx,1 ; CX = words per sector 0 0000AA14 1F pop ds ; DS:SI -> source 0 0000AA15 F3A5 rep movsw ; copy to deblocking buffer 0 0000AA17 1F pop ds ; restore SYSDAT 1412 write_buff10: 0 0000AA18 E8[0000] call write_block 0 0000AA1B 8F06[0000] pop word [cur_dma] 0 0000AA1F 8F06[0000] pop word [cur_dma_seg] 0 0000AA23 5E pop si 0 0000AA24 07 pop es 0 0000AA25 C3 ret 1419 1420 setup_rwx: 1421 ;--------- 1422 ; entry: DX:AX = sector offset (multiple FAT writes) 1423 ; ES:SI = BCB, BCB_REC filled in 1424 ; exit: all values set up for RWXIOSIF 1425 0 0000AA26 8C06[0000] mov [cur_dma_seg],es ; segment = BCB_SEGMENT 0 0000AA2A 52 push dx 0 0000AA2B 8D5414 lea dx,[BCB_DATA + si] 0 0000AA2E 8916[0000] mov [cur_dma],dx ; offset 0 0000AA32 5A pop dx 1431 ; xor dx,dx 0 0000AA33 26034406 add ax,[es:BCB_REC + si] 1433 ; adc dl,es:byte ptr BCB_REC2[si] 0 0000AA37 26135408 adc dx,[es:BCB_REC2 + si] 0 0000AA3B A3[0000] mov word ptr [pblock],ax ; xfer starts at this block 0 0000AA3E 8916[0200] mov word ptr [pblock+2],dx 0 0000AA42 C706[0000]0100 mov word [mult_sec],1 ; single sector transfer 0 0000AA48 C3 ret 1439 1440 read_fsinfo: 0 0000AA49 833E[0000]00 cmp word [dosfat],FAT32 ; is this a FAT32 partition? 0 0000AA4E 752E jne read_fsinfo10 ; no, then there is no fs info block 1443 read_fsinfo05: 0 0000AA50 06 push es 0 0000AA51 1E push ds 0 0000AA52 268B5727 mov dx,[es:DDSC_FSINFO + bx] ; sector number of FS info block 0 0000AA56 31C0 xor ax,ax 0 0000AA58 B908FF mov cx,0FF00h+BF_ISDAT ; data buffer with preread 0 0000AA5B 06 push es 0 0000AA5C 53 push bx 0 0000AA5D E860FD call locate_buffer ; read FS info block 0 0000AA60 5B pop bx 0 0000AA61 1F pop ds 0 0000AA62 268B84FC01 mov ax,word ptr [es:BCB_DATA+FS_BFREE + si] ; free cluster count in FS info block 0 0000AA67 268B94FE01 mov dx,word ptr [es:BCB_DATA+FS_BFREE+2 + si] 0 0000AA6C 894721 mov word ptr [DDSC_BFREE + bx],ax ; use this as new free cluster count 0 0000AA6F 895723 mov word ptr [DDSC_BFREE+2 + bx],dx 0 0000AA72 268B840002 mov ax,word ptr [es:BCB_DATA+FS_BBLOCK + si] ; next free block in FS info block 0 0000AA77 268B940202 mov dx,word ptr [es:BCB_DATA+FS_BBLOCK+2 + si] 1460 1461 ; TODO: why is DDSC_BBLOCK not actually set here? (Boeckmann) 1462 0 0000AA7C 1F pop ds 0 0000AA7D 07 pop es 1465 read_fsinfo10: 0 0000AA7E C3 ret 1467 1468 write_fsinfo: 0 0000AA7F 833E[0000]00 cmp word [dosfat],FAT32 ; is this a FAT32 partition? 0 0000AA84 753C jne write_fsinfo10 ; no, then there is no fs info block 0 0000AA86 06 push es 0 0000AA87 1E push ds 0 0000AA88 268B5727 mov dx,[es:DDSC_FSINFO + bx] ; sector number of FS info block 0 0000AA8C 31C0 xor ax,ax 0 0000AA8E B908FF mov cx,0FF00h+BF_ISDAT ; data buffer with preread 0 0000AA91 06 push es 0 0000AA92 53 push bx 0 0000AA93 E82AFD call locate_buffer ; read FS info block 0 0000AA96 5B pop bx 0 0000AA97 1F pop ds 0 0000AA98 8B4721 mov ax,word ptr [DDSC_BFREE + bx] ; update buffer 0 0000AA9B 8B5723 mov dx,word ptr [DDSC_BFREE+2 + bx] 0 0000AA9E 268984FC01 mov word ptr [es:BCB_DATA+FS_BFREE + si],ax 0 0000AAA3 268994FE01 mov word ptr [es:BCB_DATA+FS_BFREE+2 + si],dx 0 0000AAA8 8B473B mov ax,word ptr [DDSC_BBLOCK + bx] 0 0000AAAB 8B573D mov dx,word ptr [DDSC_BBLOCK+2 + bx] 0 0000AAAE 2689840002 mov word ptr [es:BCB_DATA+FS_BBLOCK + si],ax 0 0000AAB3 2689940202 mov word ptr [es:BCB_DATA+FS_BBLOCK+2 + si],dx 0 0000AAB8 26804C0540 or byte [es:BCB_FLAGS + si],BF_DIRTY ; mark buffer as modified 0 0000AABD 1F pop ds 0 0000AABE E8E9FD call flush_buffer ; and write it back to disk 0 0000AAC1 07 pop es 1493 write_fsinfo10: 0 0000AAC2 C3 ret 1495 1496 BDOS_CODE ends 1497 1498 END === Trace listing source: drdos/bin/bdevio.lst 1 ;title 'BDEVIF - Block DEVice Input/Output support' 2 ; File : $BDEVIO.ASM$ 3 ; 4 ; Description : 5 ; 6 ; Original Author : DIGITAL RESEARCH 7 ; 8 ; Last Edited By : $CALDERA$ 9 ; 10 ;-----------------------------------------------------------------------; 11 ; Copyright Work of Caldera, Inc. All Rights Reserved. 12 ; 13 ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, 14 ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. 15 ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES 16 ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF 17 ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO 18 ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE 19 ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE 20 ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, 21 ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, 22 ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, 23 ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF 24 ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT 25 ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND 26 ; CIVIL LIABILITY. 27 ;-----------------------------------------------------------------------; 28 ; 29 ; *** Current Edit History *** 30 ; *** End of Current Edit History *** 31 ; 32 ; $Log$ 33 ; BDEVIO.A86 1.27 94/11/30 16:25:22 34 ; added delayed retry for read/write to locked region 35 ; added support for using multiple FAT copies on reads if one fails; 36 ; BDEVIO.A86 1.26 94/02/22 17:11:25 37 ; Fix where corrupt dir entry results in read beyond end-of-chain (Filelink bug) 38 ; BDEVIO.A86 1.25 93/12/15 03:07:11 39 ; New ddioif entry point so Int 25/26 bypasses address normalisation 40 ; BDEVIO.A86 1.24 93/12/08 03:15:14 41 ; Force rebuild_ldt_root if root in JOIN's subdirectory 42 ; BDEVIO.A86 1.23 93/11/19 18:29:29 43 ; Fix for SERVER print queue viewing problem 44 ; BDEVIO.A86 1.22 93/09/21 12:43:37 45 ; On fdos read/write do EOF checks before SHARE LOCK checks 46 ; BDEVIO.A86 1.21 93/09/14 20:02:50 47 ; Trust LFLG_PHYSICAL 48 ; BDEVIO.A86 1.20 93/09/02 22:22:56 49 ; Use 32 bit sectors to read fat for build bpb if appropriate (SYQUEST bug) 50 ; BDEVIO.A86 1.19 93/08/27 18:46:49 51 ; int 26 discards hash codes 52 ; BDEVIO.A86 1.18 93/07/20 22:42:25 53 ; Even fewer checks on int 25/26 54 ; BDEVIO.A86 1.12 93/06/23 02:57:07 55 ; Add auto-commit to fdowrw 56 ; BDEVIO.A86 1.11 93/05/14 13:47:41 57 ; Shorten media change code slightly 58 ; BDEVIO.A86 1.9 93/03/16 22:30:21 IJACK 59 ; UNDELETE support changes 60 ; ENDLOG 61 62 group PCMCODE BDOS_CODE 63 group PCMDATA BDOS_DATA PCMODE_DATA 64 65 ASSUME CS:PCMCODE,DS:PCMDATA 66 67 [list -] 75 76 ;***************************************************** 77 ;* 78 ;* bdos data area 79 ;* 80 ;***************************************************** 81 === Switch to base=00C180h -> "PCMODE_DATA" 82 section PCMODE_DATA public align=2 class=DATA 83 extrn current_ddsc:dword 84 extrn current_dhndl:dword 85 extrn current_dsk:byte ; default drive 86 extrn current_ldt:dword ; currently selected LDT 87 extrn dma_offset:word ; DTA offset 88 extrn dma_segment:word ; DTA segment 89 extrn ddsc_ptr:dword 90 extrn err_drv:byte 91 extrn error_dev:dword ; failing device for Int 24's 92 extrn fdos_stub:dword 93 extrn ioexerr:byte 94 extrn last_drv:byte 95 extrn ldt_ptr:dword 96 extrn lock_bios:dword 97 extrn phys_drv:byte 98 extrn rwmode:byte 99 extrn share_stub:dword 100 extrn unlock_bios:dword 101 extrn verify_flag:byte 102 extrn net_retry:word 103 PCMODE_DATA ends 104 105 === Switch to base=00C180h -> "BDOS_DATA" 106 section BDOS_DATA public align=2 class=DATA 107 108 extrn bcb_root:dword 109 extrn deblock_seg:word 110 extrn fdos_hds_drv:byte 111 extrn fdos_hds_blk:word 112 extrn fdos_hds_root:word 113 extrn fdos_ret:word 114 115 public adrive 116 public clsize 117 public dosfat 118 public cur_dma 119 public cur_dma_seg 120 public datadd 121 public diradd 122 public dirinroot 123 public dirperclu 124 public fatadd 125 public hdsaddr 126 public lastcl 127 public blastcl 128 public logical_drv 129 public mult_sec 130 public nfatrecs 131 public nfats 132 public pblock 133 public physical_drv 134 public psecsiz 135 public req_hdr 136 public secperclu 137 public fsroot 138 139 ; The following specify the drive selected for the current operation 140 0 000019BA 0000 hdsaddr dw 0 ; current HDS address (0 means at root) 0 000019BC 00 logical_drv db 0 ; logical drive number 0 000019BD 00 physical_drv db 0 ; physical disk number 144 145 ; The following describe the currently active drive - not this may differ from 146 ; the currently selected drive above due to eg. flushing dirty buffers 147 148 ; Local copy of DDSC_ variables - ORDER CRITICAL - must match DDSC_ 149 150 local_ddsc label byte 0 000019BE 0000 psecsiz dw 0 ; byte size of sector 0 000019C0 00 clmsk db 0 0 000019C1 00 clshf db 0 0 000019C2 0000 fatadd dw 0 ; sector offset of 1st FAT sector 0 000019C4 00 byte_nfats db 0 ; number of FAT's 0 000019C5 0000 dirinroot dw 0 ; # dir entries in root 0 000019C7 0000 datadd dw 0 ; sector offset of data sector 0 000019C9 0000 lastcl dw 0 ; # last cluster (after adjustment) 0 000019CB 0000 dw 0 ; # sectors per FAT 0 000019CD 0000 diradd dw 0 ; sector offset of 1st root DIR sector 161 162 LOCAL_DDSC_LEN equ offset $ - offset local_ddsc 163 164 local_ddsc2 label byte 165 ; dw 0,0 ; total free clusters on drive 166 ; dw 0 ; FAT flags 167 ; dw 0 ; FS info 168 ; dw 0 ; backup boot sec 0 000019CF 00000000 bdatadd dw 0,0 0 000019D3 00000000 blastcl dw 0,0 ; # last cluster (32-bit) 0 000019D7 00000000 dw 0,0 ; # sectors per FAT (32-bit) 0 000019DB 00000000 fsroot dw 0,0 ; first cluster of root dir 173 ; dw 0,0 ; next block to allocate 174 ; dw 0 ; version of file system 175 176 LOCAL_DDSC2_LEN equ offset $ - offset local_ddsc2 177 178 ; some extra parameters calculated from local_ddsc for convenience 179 0 000019DF 0000 nfats dw 0 ; # FAT's (WORD is handier) 0 000019E1 00000000 nfatrecs dw 0,0 ; # sectors per FAT (accurate version) 0 000019E5 00000000 clsize dw 0,0 ; cluster size in bytes 0 000019E9 0000 secperclu dw 0 ; # sectors per cluster 0 000019EB 0000 dirperclu dw 0 ; # dir enrties in subdir 185 0 000019ED 0000 dosfat dw 0 ; FAT length indicator (FAT12 or FAT16) 187 188 ; The following specify the next block read/write operation on the active drive 189 0 000019EF FF adrive db 0ffh ; currently active disk 0 000019F0 00000000 pblock dw 0, 0 ; absolute block address 0 000019F4 0100 mult_sec dw 1 ; multi sector count passed to xios 0 000019F6 0000 cur_dma dw 0 0 000019F8 0000 cur_dma_seg dw 0 195 0 000019FA 0000 fdrwreq dw 0 ; requested count (roundup) 197 198 public fdrwflg 0 000019FC 00 fdrwflg db 0 ; bdosrw flags 0 000019FD 0000 fdrwcnt dw 0 ; requested byte count for read/write 201 fdrwptr label dword ; disk transfer address for read/write 0 000019FF 0000 fdrwoff dw 0 ; offset for R/W DTA 0 00001A01 0000 fdrwseg dw 0 ; segment for R/W DTA 204 0 00001A03 00000000 fdrwsec dd 0 ; physical block for fdosrw 0 00001A07 0000 fdrwsecoff dw 0 ; offset within sector 0 00001A09 0000 fdrwdircnt dw 0 ; # sectors in direct xfer 208 0 00001A0B 0000 byteoff dw 0 ; fdosrw local variable 0 00001A0D 0000 dw 0 ; byte offset with file 0 00001A0F 00000000 dw 0,0 212 0 00001A13 0000000000000000 fsize dw 0,0,0,0 ; used for file size calculations 0 00001A1B 0000000000000000 lastpos dw 0,0,0,0 ; last position that has been written 215 0 00001A23 00000000 blk dw 0,0 ; current cluster of filepos 0 00001A27 00000000 blkidx dw 0,0 ; current cluster index within file 0 00001A2B 00000000 blkoffset dw 0,0 ; offset within cluster 219 0 00001A2F 00000000 fdrw_seek_cl dw 0,0 0 00001A33 00000000 fdw_trunc_cl dw 0,0 0 00001A37 00000000 fdw_extend_cl dw 0,0 0 00001A3B 00000000 check_cont_cl dw 0,0 224 0 00001A3F 0000000000000000 lasttsc dw 0,0,0,0 0 00001A47 0000 tscsel dw 0 0 00001A49 000000000000000000 tsc1 dw 0,0,0,0,0,0,0,0 0 00001A52 00000000000000 0 00001A59 000000000000000000 tsc2 dw 0,0,0,0,0,0,0,0 0 00001A62 00000000000000 0 00001A69 000000000000000000 tsc3 dw 0,0,0,0,0,0,0,0 0 00001A72 00000000000000 230 231 ; static request header for DOS device driver I/O 232 233 Public req_hdr 234 235 req_hdr label byte 0 00001A79 16 req_len db 22 0 00001A7A 00 req_unit db 0 0 00001A7B 00 req_cmd db 0 0 00001A7C 0000 req_status dw 0 0 00001A7E 00 req_rwmode db 0 ; action hint for device drivers 0 00001A7F 00000000000000 db 7 dup (0) 0 00001A86 00 req_media db 0 0 00001A87 000000000000000000 db 16 dup (0) 0 00001A90 00000000000000 244 245 labelsize req1_return, byte, req_media+1 246 labelsize req1_volid, word, req_media+2 247 248 labelsize req2_buffer, word, req_media+1 249 labelsize req2_bpb, word, req_media+5 250 251 labelsize req3_buffer, word, req_media+1 252 labelsize req3_count, word, req_media+5 253 labelsize req3_sector, word, req_media+7 254 labelsize req3_volid, word, req_media+9 255 256 labelsize req4_buffer, word, req_media+1 257 labelsize req4_count, word, req_media+5 258 labelsize req4_sector, word, req_media+7 259 labelsize req4_volid, dword, req_media+9 260 labelsize req4_bigsector, dword, req_media+13 261 262 BDOS_DATA ends 263 264 === Switch to base=000000h -> "BDOS_CODE" 265 section BDOS_CODE public align=1 class=CODE 266 267 extrn alloc_chain:near 268 extrn bpb2ddsc:near ; converts BPB to DDSC 269 extrn buffers_check:near ; look for buffers 270 extrn delfat:near 271 extrn discard_all:near ; discard all buffers 272 extrn discard_dir:near ; discard directory buffers 273 extrn discard_dirty:near ; discard all dirty buffers 274 extrn discard_files:near ; discard open files 275 extrn fdos_error:near 276 extrn fdos_restart:near 277 extrn file_update:near 278 extrn fixfat:near 279 extrn getnblk:near ; get block value from FAT 280 extrn get_ldt:near 281 extrn get_ldt_raw:near 282 extrn hdsblk:near ; get current HDS block 283 extrn hshdscrd:near 284 extrn locate_buffer:near 285 extrn rebuild_ldt_root:near 286 extrn timestamp_dhndl:near 287 extrn update_dat:near 288 extrn update_fat:near 289 extrn share_delay:near 290 extrn fatptr_tag:near 291 292 public block_device_driver 293 public clus2sec 294 public device_driver 295 public read_block 296 public select_adrive 297 public select_logical_drv 298 public select_physical_drv 299 public write_block 300 public div32 301 public mul32 302 public div64 303 public mul64 304 305 public get_ddsc 306 307 get_ddsc: 308 ;-------- 309 ; On Entry: 310 ; AL = physical drive 311 ; On Exit: 312 ; CY set if bad drive, else 313 ; ES:BX -> DDSC_ 314 ; (All other registers preserved) 315 ; 0 0000AAC3 363A06[0000] cmp al,[ss:phys_drv] 0 0000AAC8 7316 jae get_ddsc30 0 0000AACA 36C41E[0000] les bx,[ss:ddsc_ptr] 319 get_ddsc10: 0 0000AACF 83FBFF cmp bx,0FFFFh ; end of the line 0 0000AAD2 740C je get_ddsc30 0 0000AAD4 263A07 cmp al,[es:DDSC_UNIT + bx] ; does the unit match ? 0 0000AAD7 7406 je get_ddsc20 ; no, try the next 0 0000AAD9 26C45F19 les bx,[es:DDSC_LINK + bx] 0 0000AADD EBF0 jmp get_ddsc10 326 get_ddsc20: 327 ; clc 0 0000AADF C3 ret 329 get_ddsc30: 0 0000AAE0 F9 stc 0 0000AAE1 C3 ret 332 333 ; Read/Write from/to disk file 334 335 ; entry: CURRENT_DNHDL -> file handle 336 ; BDRWFLG = 1 => read 337 ; 0 => write 338 ; ES:DI = buffer (32 bit: off/seg) 339 ; CX = requested byte count (16 bit) 340 341 ; exit: FDOS_RET = number of bytes read/written 342 ; CURRENT_DHNDL incremented by FDOS_RET 343 344 public fdosrw ; read/write to/from disk file 345 346 fdosrw: 347 ;------ 0 0000AAE2 E8FC01 call fdrw_prepare ; set up address, where we are in file 0 0000AAE5 7219 jc fdrw_error ; stop if we have a problem 0 0000AAE7 E8EF02 call fdrw_size ; extend file if necessary 0 0000AAEA 7214 jc fdrw_error ; bail out if we can't 0 0000AAEC 833E[4300]00 cmp word [fdrwcnt],0 ; are we truncating? 0 0000AAF1 750E jne fdrw_loop ; read/write if non-zero count 0 0000AAF3 F606[4200]01 test byte [fdrwflg],1 ; writing zero bytes? 0 0000AAF8 7506 jnz fdrw_error ; (reading has no meaning) 0 0000AAFA E82501 call fdw_trunc ; writing truncates the file 0 0000AAFD E91301 jmp fdrw_nobigger 358 fdrw_error: 0 0000AB00 C3 ret 360 361 fdrw_loop: ; loop here for long reads/writes 0 0000AB01 E87004 call fdrw_seek ; seek to position for xfer 363 ; jc fdrw_exit ; should get error's now... 0 0000AB04 7303 jnc fdrw_noerror 0 0000AB06 E9A300 jmp fdrw_exit 366 fdrw_noerror: 0 0000AB09 753D jnz fdrw_buffered ; deblocking required if not aligned 0 0000AB0B 8B0E[4300] mov cx,[fdrwcnt] ; CX = requested transfer size 0 0000AB0F 3B0E[0400] cmp cx,[psecsiz] ; at least one sector transferred? 370 ; jb fdrw_buffered ; if less, need deblocked transfer 0 0000AB13 732A jae fdrw_direct 0 0000AB15 F606[4200]01 test byte [fdrwflg],1 0 0000AB1A 752C jnz fdrw_buffered 0 0000AB1C A1[5100] mov ax,[byteoff] 0 0000AB1F 2B06[6100] sub ax,[lastpos] 0 0000AB23 A1[5300] mov ax,[byteoff+2] 0 0000AB26 1B06[6300] sbb ax,[lastpos+2] 0 0000AB2A A1[5500] mov ax,[byteoff+4] 0 0000AB2D 1B06[6500] sbb ax,[lastpos+4] 0 0000AB31 A1[5700] mov ax,[byteoff+6] 0 0000AB34 1B06[6700] sbb ax,[lastpos+6] 0 0000AB38 720E jc fdrw_buffered 0 0000AB3A E83E05 call deblock_rw_npr 0 0000AB3D EB0C jmp fdrw_more 385 fdrw_direct: 0 0000AB3F 890E[4000] mov [fdrwreq],cx ; requested count for direct r/w 0 0000AB43 E88505 call direct_rw ; transfer straight to/from TPA 0 0000AB46 EB03 jmp fdrw_more 389 fdrw_buffered: ; perform deblocked read/write 0 0000AB48 E83505 call deblock_rw ; transfer via BDOS buffer 391 fdrw_more: 0 0000AB4B 0106[4500] add [fdrwoff],ax ; adjust buffer address 0 0000AB4F 0106[0000] add [fdos_ret],ax ; adjust return code 394 0 0000AB53 0106[5100] add [byteoff],ax ; adjust file offset 0 0000AB57 8316[5300]00 adc word [byteoff+2],0 0 0000AB5C 8316[5500]00 adc word [byteoff+4],0 0 0000AB61 8316[5700]00 adc word [byteoff+6],0 399 0 0000AB66 50 push ax 0 0000AB67 A1[0400] mov ax,[psecsiz] 0 0000AB6A 48 dec ax 0 0000AB6B 0B06[6100] or ax,[lastpos] 0 0000AB6F 2B06[5100] sub ax,[byteoff] 0 0000AB73 A1[6300] mov ax,[lastpos+2] 0 0000AB76 1B06[5300] sbb ax,[byteoff+2] 0 0000AB7A A1[6500] mov ax,[lastpos+4] 0 0000AB7D 1B06[5500] sbb ax,[byteoff+4] 0 0000AB81 A1[6700] mov ax,[lastpos+6] 0 0000AB84 1B06[5700] sbb ax,[byteoff+6] 0 0000AB88 7318 jnc fdrw_nohigher 0 0000AB8A A1[5100] mov ax,[byteoff] 0 0000AB8D A3[6100] mov [lastpos],ax 0 0000AB90 A1[5300] mov ax,[byteoff+2] 0 0000AB93 A3[6300] mov [lastpos+2],ax 0 0000AB96 A1[5500] mov ax,[byteoff+4] 0 0000AB99 A3[6500] mov [lastpos+4],ax 0 0000AB9C A1[5700] mov ax,[byteoff+6] 0 0000AB9F A3[6700] mov [lastpos+6],ax 420 421 fdrw_nohigher: 0 0000ABA2 58 pop ax 0 0000ABA3 2906[4300] sub [fdrwcnt],ax ; adjust remaining count 424 ; ja fdrw_loop ; still more to do 0 0000ABA7 7603 jna fdrw_exit 0 0000ABA9 E955FF jmp fdrw_loop 427 fdrw_exit: 0 0000ABAC C41E[0000] les bx,[current_dhndl] 0 0000ABB0 A1[0000] mov ax,[fdos_ret] ; get total xfered and update position 0 0000ABB3 26014715 add [es:DHNDL_POSLO + bx],ax 0 0000ABB7 2683571700 adc word [es:DHNDL_POSHI + bx],0 0 0000ABBC 2683574700 adc word [es:DHNDL_POSXLO + bx],0 0 0000ABC1 2683574900 adc word [es:DHNDL_POSXHI + bx],0 0 0000ABC6 F606[4200]01 test byte [fdrwflg],1 0 0000ABCB 7554 jnz fdrw_return ; skip if reading 436 ; mov ax,byteoff ; has the file grown ? 437 ; mov dx,byteoff+WORD 438 ; sub ax,es:DHNDL_SIZELO[bx] 439 ; sbb dx,es:DHNDL_SIZEHI[bx] 0 0000ABCD A1[5100] mov ax,[byteoff] 0 0000ABD0 262B4711 sub ax,[es:DHNDL_SIZELO + bx] 0 0000ABD4 A3[5900] mov [fsize],ax 0 0000ABD7 A1[5300] mov ax,[byteoff+2] 0 0000ABDA 261B4713 sbb ax,[es:DHNDL_SIZEHI + bx] 0 0000ABDE A3[5B00] mov [fsize+2],ax 0 0000ABE1 A1[5500] mov ax,[byteoff+4] 0 0000ABE4 261B4743 sbb ax,[es:DHNDL_SIZEXLO + bx] 0 0000ABE8 A3[5D00] mov [fsize+4],ax 0 0000ABEB A1[5700] mov ax,[byteoff+6] 0 0000ABEE 261B4745 sbb ax,[es:DHNDL_SIZEXHI + bx] 0 0000ABF2 A3[5F00] mov [fsize+6],ax 0 0000ABF5 721C jb fdrw_nobigger ; yes, update the file size 453 ; add es:DHNDL_SIZELO[bx],ax 454 ; adc es:DHNDL_SIZEHI[bx],dx 0 0000ABF7 A1[5900] mov ax,[fsize] 0 0000ABFA 26014711 add [es:DHNDL_SIZELO + bx],ax 0 0000ABFE A1[5B00] mov ax,[fsize+2] 0 0000AC01 26114713 adc [es:DHNDL_SIZEHI + bx],ax 0 0000AC05 A1[5D00] mov ax,[fsize+4] 0 0000AC08 26114743 adc [es:DHNDL_SIZEXLO + bx],ax 0 0000AC0C A1[5F00] mov ax,[fsize+6] 0 0000AC0F 26114745 adc [es:DHNDL_SIZEXHI + bx],ax 463 fdrw_nobigger: 0 0000AC13 E8[0000] call timestamp_dhndl ; record the current time 0 0000AC16 26F747020040 test word [es:DHNDL_MODE + bx],DHM_COMMIT 0 0000AC1C 7403 jz fdrw_return ; is auto-commit in place ? 0 0000AC1E E8[0000] call file_update ; yes, commit the file 468 fdrw_return: 0 0000AC21 C3 ret 470 471 472 473 fdw_trunc: 474 ;--------- 475 ; On Entry: 476 ; BLKIDX = block number within file 477 ; BLKOFFSET = block offset 478 ; On Exit: 479 ; DHNDL_SIZE adjusted, any excess clusters freed 480 ; 481 0 0000AC22 C41E[0000] les bx,[current_dhndl] 483 ; mov cx,blkoffset ; get offset within current block 0 0000AC26 A1[6D00] mov ax,[blkidx] ; get logical block number 0 0000AC29 8B16[6F00] mov dx,[blkidx+2] 0 0000AC2D 833E[7100]00 cmp word [blkoffset],0 ; get offset within current block 487 ; jcxz fdw_t10 ; skip if no data in last block 0 0000AC32 7507 jnz fdw_t05 ; skip if no data in last block 0 0000AC34 833E[7300]00 cmp word [blkoffset+2],0 0 0000AC39 7406 jz fdw_t10 491 fdw_t05: 492 ; inc ax ; else add in another cluster 0 0000AC3B 83C001 add ax,1 ; else add in another cluster 0 0000AC3E 83D200 adc dx,0 495 fdw_t10: ; AX = # of clusters required in file 0 0000AC41 85C0 test ax,ax 0 0000AC43 750E jnz fdw_t20 0 0000AC45 85D2 test dx,dx 0 0000AC47 750A jnz fdw_t20 0 0000AC49 2687470B xchg ax,[es:DHNDL_BLK1 + bx] ; forget about chain 0 0000AC4D 2687573B xchg dx,[es:DHNDL_BLK1H + bx] 0 0000AC51 EB55 jmp fdw_t50 503 504 fdw_t20: 505 ; xchg ax,cx ; CX = # of blocks to keep 0 0000AC53 A3[7900] mov [fdw_trunc_cl],ax ; # of blocks to keep 0 0000AC56 8916[7B00] mov [fdw_trunc_cl+2],dx 0 0000AC5A 268B470B mov ax,[es:DHNDL_BLK1 + bx] ; get first block in file 0 0000AC5E 268B573B mov dx,[es:DHNDL_BLK1H + bx] 510 fdw_t30: ; scan all block we want to keep 511 ; push cx 0 0000AC62 52 push dx 0 0000AC63 50 push ax 0 0000AC64 E8[0000] call getnblk ; get next block 0 0000AC67 5B pop bx 0 0000AC68 59 pop cx 517 ; cmp ax,lastcl ; stop on premature end of chain 0 0000AC69 3B16[1B00] cmp dx,[blastcl+2] ; stop on premature end of chain 0 0000AC6D 773C ja fdw_t60 0 0000AC6F 7206 jb fdw_t35 0 0000AC71 3B06[1900] cmp ax,[blastcl] 0 0000AC75 7734 ja fdw_t60 523 fdw_t35: 524 ; loop fdw_t30 0 0000AC77 832E[7900]01 sub word [fdw_trunc_cl],1 0 0000AC7C 831E[7B00]00 sbb word [fdw_trunc_cl+2],0 0 0000AC81 833E[7B00]00 cmp word [fdw_trunc_cl+2],0 0 0000AC86 75DA jne fdw_t30 0 0000AC88 833E[7900]00 cmp word [fdw_trunc_cl],0 0 0000AC8D 75D3 jne fdw_t30 0 0000AC8F 52 push dx 0 0000AC90 50 push ax ; yep, remember what 0 0000AC91 A1[3300] mov ax,[dosfat] 0 0000AC94 31D2 xor dx,dx 0 0000AC96 83F800 cmp ax,FAT32 ; FAT32 file system? 0 0000AC99 7505 jne fdw_t36 ; no, proceed normally 0 0000AC9B B8FFFF mov ax,FAT16 ; use 0ffffh instead 0 0000AC9E 89C2 mov dx,ax 539 fdw_t36: 0 0000ACA0 93 xchg ax,bx ; truncate chain at cluster AX 0 0000ACA1 87D1 xchg dx,cx 0 0000ACA3 E8[0000] call fixfat ; as thats all we need 0 0000ACA6 58 pop ax 0 0000ACA7 5A pop dx 545 fdw_t50: 0 0000ACA8 E8[0000] call delfat ; release the chain 547 fdw_t60: 0 0000ACAB C41E[0000] les bx,[current_dhndl] 0 0000ACAF A1[5100] mov ax,[byteoff] ; now truncate the file 0 0000ACB2 26894711 mov [es:DHNDL_SIZELO + bx],ax 0 0000ACB6 A1[5300] mov ax,[byteoff+2] 0 0000ACB9 26894713 mov [es:DHNDL_SIZEHI + bx],ax 0 0000ACBD A1[5500] mov ax,[byteoff+4] 0 0000ACC0 26894743 mov [es:DHNDL_SIZEXLO + bx],ax 0 0000ACC4 A1[5700] mov ax,[byteoff+6] 0 0000ACC7 26894745 mov [es:DHNDL_SIZEXHI + bx],ax 0 0000ACCB 31C0 xor ax,ax ; cause reads/writes to scan 0 0000ACCD 26894735 mov [es:DHNDL_BLK + bx],ax ; block chain from start 0 0000ACD1 26894741 mov [es:DHNDL_BLKH + bx],ax 0 0000ACD5 26894719 mov [es:DHNDL_IDX + bx],ax 0 0000ACD9 2689473D mov [es:DHNDL_IDXH + bx],ax 0 0000ACDD A3[0000] mov [fdos_ret],ax ; no logical errors 0 0000ACE0 C3 ret 564 565 566 567 fdrw_prepare: 568 ;------------ 569 ; Normalise the xfer address and count 570 ; Calculate current position in the file 571 ; 572 ; On Entry: 573 ; ES:DI -> buffer 574 ; CX = bytes to xfer 575 ; On Exit: 576 ; FDRWSEG:FDRWOFF -> normalised buffer 577 ; FDRWCNT = bytes to xfer 578 ; FDOS_RET = bytes xfer'd (0) 579 ; PREREAD = TRUE 580 ; BYTEOFF = current offset in file 581 ; BLKIDX = cluster containing current file position 582 ; BLKOFFSET = offset within cluster 583 ; CY set if current position theoretically impossible 584 ; 585 0 0000ACE1 31C0 xor ax,ax ; AX = 0 0 0000ACE3 A3[0000] mov [fdos_ret],ax ; initialize byte return count 0 0000ACE6 890E[4300] mov [fdrwcnt],cx ; save byte count for read/write 0 0000ACEA B80F00 mov ax,000Fh 0 0000ACED 21F8 and ax,di ; get offset within paragraph 0 0000ACEF A3[4500] mov [fdrwoff],ax ; save normalized offset for read/write 0 0000ACF2 01C8 add ax,cx ; do we overflow 64k ? 0 0000ACF4 7304 jnc fdrw_p10 ; yes, then forget about what would 0 0000ACF6 2906[4300] sub [fdrwcnt],ax ; overflow this segment 595 fdrw_p10: 0 0000ACFA B104 mov cl,4 0 0000ACFC D3EF shr di,cl ; DI = paragraph offset 0 0000ACFE 8CC0 mov ax,es 0 0000AD00 01F8 add ax,di ; AX = effective segment 0 0000AD02 730A jnc fdrw_p20 ; if above 1 MByte base it at FFFF 0 0000AD04 40 inc ax ; AX = para's above FFFF 0 0000AD05 D3E0 shl ax,cl ; make it bytes 0 0000AD07 0106[4500] add [fdrwoff],ax ; add to offset 0 0000AD0B B8FFFF mov ax,0ffffh ; use our magic segment 605 fdrw_p20: 0 0000AD0E A3[4700] mov [fdrwseg],ax ; save normalized segment for read/write 0 0000AD11 C41E[0000] les bx,[current_dhndl] 0 0000AD15 268B4715 mov ax,[es:DHNDL_POSLO + bx] ; copy position to local variables 0 0000AD19 A3[5100] mov [byteoff],ax 0 0000AD1C 268B4717 mov ax,[es:DHNDL_POSHI + bx] 0 0000AD20 A3[5300] mov [byteoff+2],ax 0 0000AD23 268B4747 mov ax,[es:DHNDL_POSXLO + bx] 0 0000AD27 83F83F cmp ax,63 ; greater than 256 GB-1 0 0000AD2A 7603 jbe fdrw_p25 0 0000AD2C E9A800 jmp fdrw_p40 ; then it is too big even for FAT+ 616 fdrw_p25: 0 0000AD2F A3[5500] mov [byteoff+4],ax 0 0000AD32 268B4749 mov ax,[es:DHNDL_POSXHI + bx] 0 0000AD36 83F800 cmp ax,0 620 ; ja fdrw_p40 0 0000AD39 7603 jna fdrw_p27 0 0000AD3B E99900 jmp fdrw_p40 623 fdrw_p27: 0 0000AD3E A3[5700] mov [byteoff+6],ax 0 0000AD41 268B4711 mov ax,[es:DHNDL_SIZELO + bx] ; copy file size 0 0000AD45 A3[6100] mov [lastpos],ax 0 0000AD48 268B4713 mov ax,[es:DHNDL_SIZEHI + bx] 0 0000AD4C A3[6300] mov [lastpos+2],ax 0 0000AD4F 268B4743 mov ax,[es:DHNDL_SIZEXLO + bx] 0 0000AD53 A3[6500] mov [lastpos+4],ax 0 0000AD56 268B4745 mov ax,[es:DHNDL_SIZEXHI + bx] 0 0000AD5A A3[6700] mov [lastpos+6],ax 633 ; mov cx,clsize 634 ; mov ax,lastcl 635 ; mul cx ; DX:AX = maximum size of disk 0 0000AD5D FF36[2D00] push word [clsize+2] 0 0000AD61 FF36[2B00] push word [clsize] 0 0000AD65 FF36[1B00] push word [blastcl+2] 0 0000AD69 FF36[1900] push word [blastcl] 0 0000AD6D 83EC08 sub sp,8 ; reserve space on stack 0 0000AD70 E89909 call mul32 ; compute maximum size of disk 642 ; pop ax 643 ; pop dx 644 ; pop cx 0 0000AD73 8F06[5900] pop word [fsize] 0 0000AD77 8F06[5B00] pop word [fsize+2] 0 0000AD7B 8F06[5D00] pop word [fsize+4] 0 0000AD7F 8F06[5F00] pop word [fsize+6] 649 ; add sp,10 ; clean up the stack again 0 0000AD83 83C408 add sp,8 ; clean up the stack again 651 ; sub ax,byteoff 652 ; sbb dx,byteoff+WORD ; beyond this we can't go 653 ; sbb cx,0 0 0000AD86 A1[5900] mov ax,[fsize] 0 0000AD89 2B06[5100] sub ax,[byteoff] 0 0000AD8D A1[5B00] mov ax,[fsize+2] 0 0000AD90 1B06[5300] sbb ax,[byteoff+2] 0 0000AD94 A1[5D00] mov ax,[fsize+4] 0 0000AD97 1B06[5500] sbb ax,[byteoff+4] 0 0000AD9B A1[5F00] mov ax,[fsize+6] 0 0000AD9E 1B06[5700] sbb ax,[byteoff+6] 0 0000ADA2 7232 jc fdrw_p30 663 ; mov ax,byteoff ; DX:AX = current file size 664 ; mov dx,byteoff+WORD 665 ; div clsize 666 ; mov blkidx,ax ; save it for later 667 ; mov blkoffset,dx ; DX = offset within cluster 0 0000ADA4 FF36[5700] push word [byteoff+6] ; current file size 0 0000ADA8 FF36[5500] push word [byteoff+4] 0 0000ADAC FF36[5300] push word [byteoff+2] 0 0000ADB0 FF36[5100] push word [byteoff] 0 0000ADB4 FF36[2D00] push word [clsize+2] 0 0000ADB8 FF36[2B00] push word [clsize] 0 0000ADBC 83EC08 sub sp,8 ; reserve space on stack 675 ; call div32 0 0000ADBF E83E08 call div64 0 0000ADC2 8F06[7100] pop word [blkoffset] ; offset within cluster 0 0000ADC6 8F06[7300] pop word [blkoffset+2] 679 ; add sp,2 ; skip high word 0 0000ADCA 8F06[6D00] pop word [blkidx] ; save it for later 0 0000ADCE 8F06[6F00] pop word [blkidx+2] 682 ; add sp,8 ; clean up stack 0 0000ADD2 83C40C add sp,12 ; clean up stack 0 0000ADD5 F8 clc ; theoretically possible 685 fdrw_p30: 0 0000ADD6 C3 ret 687 688 fdrw_p40: 0 0000ADD7 F9 stc 0 0000ADD8 C3 ret 691 692 fdrw_size: 693 ;--------- 694 ; On reads check xfer starts within file, and clip size to reflect EOF. 695 ; On writes try to extend to cluster chain so it is big enough to contain 696 ; the data we wish to write. 697 ; 698 ; On Entry: 699 ; BYTEOFF = current position in file 700 ; FDRWCNT = extra bytes requested 701 ; On Exit: 702 ; FDRWCNT adjusted if read past EOF 703 ; CY set if problem extending file 704 ; 0 0000ADD9 C41E[0000] les bx,[current_dhndl] 706 ; mov ax,es:DHNDL_SIZELO[bx] ; are we past the end of file 707 ; mov dx,es:DHNDL_SIZEHI[bx] ; if so we may wish to extend on write 708 ; sub ax,byteoff ; AX,DX = current offset 709 ; sbb dx,byteoff+WORD ; are we already beyond EOF ? 0 0000ADDD 268B4711 mov ax,[es:DHNDL_SIZELO + bx] 0 0000ADE1 2B06[5100] sub ax,[byteoff] 0 0000ADE5 A3[5900] mov [fsize],ax 0 0000ADE8 268B4713 mov ax,[es:DHNDL_SIZEHI + bx] 0 0000ADEC 1B06[5300] sbb ax,[byteoff+2] 0 0000ADF0 A3[5B00] mov [fsize+2],ax 0 0000ADF3 268B4743 mov ax,[es:DHNDL_SIZEXLO + bx] 0 0000ADF7 1B06[5500] sbb ax,[byteoff+4] 0 0000ADFB A3[5D00] mov [fsize+4],ax 0 0000ADFE 268B4745 mov ax,[es:DHNDL_SIZEXHI + bx] 0 0000AE02 1B06[5700] sbb ax,[byteoff+6] 0 0000AE06 A3[5F00] mov [fsize+6],ax 0 0000AE09 7242 jb fdrw_s40 723 ; sub ax,fdrwcnt ; will we be going beyond EOF ? 724 ; sbb dx,0 0 0000AE0B A1[4300] mov ax,[fdrwcnt] 0 0000AE0E 2906[5900] sub [fsize],ax 0 0000AE12 831E[5B00]00 sbb word [fsize+2],0 0 0000AE17 831E[5D00]00 sbb word [fsize+4],0 0 0000AE1C 831E[5F00]00 sbb word [fsize+6],0 0 0000AE21 730E jnb fdrw_s10 ; no, whole xfer is OK 0 0000AE23 F606[4200]01 test byte [fdrwflg],1 ; check if we're reading 0 0000AE28 742B jz fdrw_s50 ; if we are just adjust the 0 0000AE2A A1[5900] mov ax,[fsize] 0 0000AE2D 0106[4300] add [fdrwcnt],ax ; amount we can xfer 735 fdrw_s10: 736 ; We call share concerning the XFER to check if any of the proposed 737 ; file region is locked. 738 739 ; les bx,current_dhndl ; check for locked regions 0 0000AE31 8B0E[0000] mov cx,[net_retry] 741 fdrw_s15: 0 0000AE35 51 push cx 0 0000AE36 8B0E[4300] mov cx,[fdrwcnt] ; in the file 0 0000AE3A FF1E[0C00] call far [share_stub+S_FDOSRW] 0 0000AE3E 59 pop cx 0 0000AE3F 7308 jnc fdrw_s20 ; CY set on error 0 0000AE41 49 dec cx 0 0000AE42 7406 jz fdrw_s30 0 0000AE44 E8[0000] call share_delay 0 0000AE47 EBEC jmp fdrw_s15 751 fdrw_s20: 0 0000AE49 C3 ret 753 754 fdrw_s30: 0 0000AE4A E9[0000] jmp fdos_error ; CY clear, AX = error code 756 757 758 fdrw_s40: 759 ; We are going beyond EOF - if it is a read we fail it, if a write 760 ; try to extend the file 0 0000AE4D F606[4200]01 test byte [fdrwflg],1 ; check if we're reading 0 0000AE52 F9 stc ; assume failure 0 0000AE53 75F4 jnz fdrw_s20 ; reads fail now, writes extend file 764 fdrw_s50: 0 0000AE55 E8D9FF call fdrw_s10 ; make sure SHARE doesn't object 766 ; jmp fdwrite_extend ; if not try to extend the file 767 768 769 fdwrite_extend: 770 ;-------------- 771 ; Try to extend to file to the required size before we write to it 772 ; On Entry: 773 ; ES:BX -> DHNDL_ 774 ; BYTEOFF = current position in file 775 ; FDRWCNT = extra requested 776 ; On Exit: 777 ; CY clear if cluster chain now big enough for desired file size 778 ; 779 780 ; mov ax,byteoff ; AX,DX = current offset 781 ; mov dx,byteoff+2 782 ; add ax,fdrwcnt ; AX,DX = offset after r/w if success 783 ; adc dx,0 ; add offset from lower 16 bits 0 0000AE58 A1[5100] mov ax,[byteoff] 0 0000AE5B 0306[4300] add ax,[fdrwcnt] 0 0000AE5F A3[5900] mov [fsize],ax 0 0000AE62 A1[5300] mov ax,[byteoff+2] 0 0000AE65 83D000 adc ax,0 0 0000AE68 A3[5B00] mov [fsize+2],ax 0 0000AE6B A1[5500] mov ax,[byteoff+4] 0 0000AE6E 83D000 adc ax,0 0 0000AE71 A3[5D00] mov [fsize+4],ax 0 0000AE74 A1[5700] mov ax,[byteoff+6] 0 0000AE77 83D000 adc ax,0 0 0000AE7A A3[5F00] mov [fsize+6],ax 796 ; div clsize ; AX whole blocks required 797 ; push dx 798 ; push ax 0 0000AE7D FF36[5F00] push word [fsize+6] 0 0000AE81 FF36[5D00] push word [fsize+4] 0 0000AE85 FF36[5B00] push word [fsize+2] 0 0000AE89 FF36[5900] push word [fsize] 0 0000AE8D FF36[2D00] push word [clsize+2] 0 0000AE91 FF36[2B00] push word [clsize] 0 0000AE95 83EC08 sub sp,8 806 ; call div32 0 0000AE98 E86507 call div64 0 0000AE9B 58 pop ax 0 0000AE9C 5A pop dx 0 0000AE9D 8F06[7D00] pop word [fdw_extend_cl] 0 0000AEA1 8F06[7F00] pop word [fdw_extend_cl+2] 812 ; add sp,8 0 0000AEA5 83C40C add sp,12 0 0000AEA8 85D2 test dx,dx ; any remainder ? 0 0000AEAA 7504 jnz fdw_e04 0 0000AEAC 85C0 test ax,ax 0 0000AEAE 740A jz fdw_e05 ; yes, we have a partial block 818 fdw_e04: 819 ; inc ax ; round up blocks required 0 0000AEB0 8306[7D00]01 add word [fdw_extend_cl],1 ; round up blocks required 0 0000AEB5 8316[7F00]00 adc word [fdw_extend_cl+2],0 822 fdw_e05: 823 ; xchg ax,cx ; CX blocks are required 0 0000AEBA 268B470B mov ax,[es:DHNDL_BLK1 + bx] ; assume we need to follow from start 0 0000AEBE 268B573B mov dx,[es:DHNDL_BLK1H + bx] 0 0000AEC2 85C0 test ax,ax 0 0000AEC4 7506 jnz fdw_e06 0 0000AEC6 85D2 test dx,dx 0 0000AEC8 7502 jnz fdw_e06 ; if no starting block do the lot 0 0000AECA EB79 jmp fdw_e30 831 fdw_e06: 832 ; dec cx ; else count # extra blocks required 0 0000AECC 832E[7D00]01 sub word [fdw_extend_cl],1 ; else count # extra blocks required 0 0000AED1 831E[7F00]00 sbb word [fdw_extend_cl+2],0 835 ; mov dx,es:DHNDL_BLK[bx] ; do we have a current block ? 0 0000AED6 268B4735 mov ax,[es:DHNDL_BLK + bx] ; do we have a current block ? 0 0000AEDA 268B5741 mov dx,[es:DHNDL_BLKH + bx] 0 0000AEDE 85D2 test dx,dx ; if not we have to start 0 0000AEE0 7504 jnz fdw_e07 0 0000AEE2 85C0 test ax,ax 0 0000AEE4 741A jz fdw_e10 ; with the first block 842 fdw_e07: 843 ; mov ax,dx ; new starting block as this must 0 0000AEE6 268B4735 mov ax,[es:DHNDL_BLK + bx] 0 0000AEEA 268B5741 mov dx,[es:DHNDL_BLKH + bx] 846 ; sub cx,es:DHNDL_IDX[bx] ; be less than extended size 0 0000AEEE 268B4F19 mov cx,[es:DHNDL_IDX + bx] ; be less than extended size 0 0000AEF2 290E[7D00] sub [fdw_extend_cl],cx 0 0000AEF6 268B4F3D mov cx,[es:DHNDL_IDXH + bx] 0 0000AEFA 190E[7F00] sbb [fdw_extend_cl+2],cx 0 0000AEFE EB08 jmp fdw_e11 852 fdw_e10: 0 0000AF00 268B470B mov ax,[es:DHNDL_BLK1 + bx] 0 0000AF04 268B573B mov dx,[es:DHNDL_BLK1H + bx] 855 fdw_e11: 856 ; jcxz fdw_e20 ; bail out of we have enough 0 0000AF08 833E[7F00]00 cmp word [fdw_extend_cl+2],0 0 0000AF0D 7507 jnz fdw_e15 0 0000AF0F 833E[7D00]00 cmp word [fdw_extend_cl],0 0 0000AF14 742D jz fdw_e20 ; bail out of we have enough 861 fdw_e15: 0 0000AF16 52 push dx 0 0000AF17 50 push ax ; save current block 864 ; push cx ; save # required 0 0000AF18 E8[0000] call getnblk ; AX = next block in chain 866 ; pop cx ; restore # required 0 0000AF1B 5B pop bx ; recover previous block 0 0000AF1C 59 pop cx 869 ; cmp ax,lastcl ; end of chain yet ? 0 0000AF1D 3B16[1B00] cmp dx,[blastcl+2] ; end of chain yet ? 0 0000AF21 7739 ja fdw_e40 0 0000AF23 7206 jb fdw_e17 0 0000AF25 3B06[1900] cmp ax,[blastcl] 0 0000AF29 7731 ja fdw_e40 875 fdw_e17: 876 ; loop fdw_e15 ; try another one 0 0000AF2B 832E[7D00]01 sub word [fdw_extend_cl],1 0 0000AF30 831E[7F00]00 sbb word [fdw_extend_cl+2],0 0 0000AF35 833E[7F00]00 cmp word [fdw_extend_cl+2],0 0 0000AF3A 75DA jne fdw_e15 0 0000AF3C 833E[7D00]00 cmp word [fdw_extend_cl],0 0 0000AF41 75D3 jne fdw_e15 883 fdw_e20: 0 0000AF43 F8 clc ; chain is already long enough 0 0000AF44 C3 ret 886 887 fdw_e30: 888 ; We have no initial block, so allocate them all 889 ; xor ax,ax ; no preconceptions over where we 0 0000AF45 8B0E[7D00] mov cx,[fdw_extend_cl] ; this value *should* not exceed 16 bits... 0 0000AF49 E8[0000] call alloc_chain ; allocate chain of CX clusters 0 0000AF4C 720D jc fdw_e35 0 0000AF4E C41E[0000] les bx,[current_dhndl] 0 0000AF52 2689470B mov [es:DHNDL_BLK1 + bx],ax ; remember initial block 0 0000AF56 2689573B mov [es:DHNDL_BLK1H + bx],dx 0 0000AF5A F8 clc 897 fdw_e35: 0 0000AF5B C3 ret 899 900 fdw_e40: 901 ; We have a partial chain, ending at cluster CX:BX 0 0000AF5C 51 push cx 0 0000AF5D 53 push bx ; save current end of chain 0 0000AF5E 93 xchg ax,bx ; start allocating from cluster AX a 0 0000AF5F 87D1 xchg dx,cx 0 0000AF61 8B0E[7D00] mov cx,[fdw_extend_cl] ; this value *should* not exceed 16 bits... 0 0000AF65 E8[0000] call alloc_chain ; a chain of CX clusters 0 0000AF68 5B pop bx 0 0000AF69 59 pop cx 0 0000AF6A 7207 jc fdw_e45 0 0000AF6C 93 xchg ax,bx ; AX = previous cluster, link cluster 0 0000AF6D 87D1 xchg dx,cx 0 0000AF6F E8[0000] call fixfat ; BX to end of the chain 0 0000AF72 F8 clc 915 fdw_e45: 0 0000AF73 C3 ret 917 918 919 920 fdrw_seek: 921 ;--------- 922 ; On Entry: 923 ; BYTEOFF = offset within file 924 ; On Exit: 925 ; BLK = cluster containing current filepos 926 ; BLKOFFSET = offset within cluster 927 ; BLKIDX = cluster index within file 928 ; PBLOCK = sector containing current filepos 929 ; POFFSET = offset within sector (reflected in ZF) 930 ; 931 ; mov ax,byteoff ; where are we now ? 932 ; mov dx,byteoff+WORD 933 ; div clsize 934 ; mov blkidx,ax ; save cluster 935 ; mov blkoffset,dx ; and offset within it 0 0000AF74 FF36[5700] push word [byteoff+6] ; where are we now ? 0 0000AF78 FF36[5500] push word [byteoff+4] 0 0000AF7C FF36[5300] push word [byteoff+2] 0 0000AF80 FF36[5100] push word [byteoff] 0 0000AF84 FF36[2D00] push word [clsize+2] 0 0000AF88 FF36[2B00] push word [clsize] 0 0000AF8C 83EC08 sub sp,8 ; reserve space on stack for result 943 ; call div32 0 0000AF8F E86E06 call div64 0 0000AF92 8F06[7100] pop word [blkoffset] ; save cluster and offset within it 0 0000AF96 8F06[7300] pop word [blkoffset+2] 947 ; add sp,2 0 0000AF9A 8F06[6D00] pop word [blkidx] 0 0000AF9E 8F06[6F00] pop word [blkidx+2] 950 ; add sp,8 ; clean up stack 0 0000AFA2 83C40C add sp,12 ; clean up stack 0 0000AFA5 C41E[0000] les bx,[current_dhndl] 0 0000AFA9 A1[6D00] mov ax,[blkidx] 0 0000AFAC 8B16[6F00] mov dx,[blkidx+2] 955 ; cmp ax,es:DHNDL_IDX[bx] ; do we know this block ? 0 0000AFB0 263B573D cmp dx,[es:DHNDL_IDXH + bx] ; do we know this block ? 0 0000AFB4 7230 jb fdrw_seek10 ; we can't go backwards, use 1st block 0 0000AFB6 7706 ja fdrw_seek05 0 0000AFB8 263B4719 cmp ax,[es:DHNDL_IDX + bx] 0 0000AFBC 7228 jb fdrw_seek10 961 fdrw_seek05: 962 ; mov cx,es:DHNDL_BLK[bx] ; get last index block 963 ; jcxz fdrw_seek10 ; use 1st block if it isn't valid 0 0000AFBE 268B4F35 mov cx,[es:DHNDL_BLK + bx] ; get last index block 0 0000AFC2 890E[7500] mov [fdrw_seek_cl],cx 0 0000AFC6 268B4F41 mov cx,[es:DHNDL_BLKH + bx] 0 0000AFCA 890E[7700] mov [fdrw_seek_cl+2],cx 0 0000AFCE 833E[7700]00 cmp word [fdrw_seek_cl+2],0 0 0000AFD3 7507 jne fdrw_seek06 0 0000AFD5 833E[7500]00 cmp word [fdrw_seek_cl],0 0 0000AFDA 740A je fdrw_seek10 ; use 1st block if it isn't valid 972 fdrw_seek06: 0 0000AFDC 262B4719 sub ax,[es:DHNDL_IDX + bx] ; skip this many 0 0000AFE0 261B573D sbb dx,[es:DHNDL_IDXH + bx] 0 0000AFE4 EB10 jmp fdrw_seek20 976 fdrw_seek10: 0 0000AFE6 268B4F0B mov cx,[es:DHNDL_BLK1 + bx] ; start with 1st block 0 0000AFEA 890E[7500] mov [fdrw_seek_cl],cx 0 0000AFEE 268B4F3B mov cx,[es:DHNDL_BLK1H + bx] 0 0000AFF2 890E[7700] mov [fdrw_seek_cl+2],cx 981 fdrw_seek20: 982 ; xchg ax,cx ; AX = starting cluster 983 ; jcxz fdrw_seek40 ; CX = clusters to skip 0 0000AFF6 8706[7500] xchg ax,[fdrw_seek_cl] ; DX:AX = starting cluster 0 0000AFFA 8716[7700] xchg dx,[fdrw_seek_cl+2] 0 0000AFFE 833E[7700]00 cmp word [fdrw_seek_cl+2],0 0 0000B003 7507 jne fdrw_seek30 0 0000B005 833E[7500]00 cmp word [fdrw_seek_cl],0 0 0000B00A 742B je fdrw_seek40 ; CX = clusters to skip 990 fdrw_seek30: 0 0000B00C 51 push cx 0 0000B00D E8[0000] call getnblk ; get next block 0 0000B010 59 pop cx 994 ; cmp ax,lastcl ; stop on premature end of chain 0 0000B011 3B16[1B00] cmp dx,[blastcl+2] ; stop on premature end of chain 0 0000B015 7762 ja fdrw_seek_error ; (file size must be wrong..) 0 0000B017 7206 jb fdrw_seek35 ; continue 0 0000B019 3B06[1900] cmp ax,[blastcl] 0 0000B01D 775A ja fdrw_seek_error 1000 fdrw_seek35: 1001 ; loop fdrw_seek30 0 0000B01F 832E[7500]01 sub word [fdrw_seek_cl],1 0 0000B024 831E[7700]00 sbb word [fdrw_seek_cl+2],0 0 0000B029 833E[7700]00 cmp word [fdrw_seek_cl+2],0 0 0000B02E 75DC jne fdrw_seek30 0 0000B030 833E[7500]00 cmp word [fdrw_seek_cl],0 0 0000B035 75D5 jne fdrw_seek30 1008 fdrw_seek40: 0 0000B037 C41E[0000] les bx,[current_dhndl] 0 0000B03B 52 push dx 0 0000B03C 50 push ax 1012 ; mov dx,blkidx 0 0000B03D A1[6D00] mov ax,[blkidx] 0 0000B040 8B16[6F00] mov dx,[blkidx+2] 1015 ; mov es:DHNDL_IDX[bx],dx ; remember this position for next time 0 0000B044 26894719 mov [es:DHNDL_IDX + bx],ax ; remember this position for next time 0 0000B048 2689573D mov [es:DHNDL_IDXH + bx],dx 0 0000B04C 58 pop ax 0 0000B04D 5A pop dx 0 0000B04E 26894735 mov [es:DHNDL_BLK + bx],ax 0 0000B052 26895741 mov [es:DHNDL_BLKH + bx],dx 0 0000B056 A3[6900] mov [blk],ax ; save the block for coniguous checks 0 0000B059 8916[6B00] mov [blk+2],dx 0 0000B05D E8[0000] call fatptr_tag 0 0000B060 8B1E[7100] mov bx,[blkoffset] 0 0000B064 8B0E[7300] mov cx,[blkoffset+2] 0 0000B068 E86205 call clus2sec ; convert to sector/offset 0 0000B06B A3[4900] mov word ptr [fdrwsec],ax ; remember this block 0 0000B06E 8916[4B00] mov word ptr [fdrwsec+2],dx 0 0000B072 891E[4D00] mov [fdrwsecoff],bx ; and offset within it 0 0000B076 85DB test bx,bx ; set ZF 1032 ; clc ; no problems 0 0000B078 C3 ret 1034 1035 fdrw_seek_error: 0 0000B079 F9 stc ; we hit unexpected end of chain 0 0000B07A C3 ret ; (shouldn't happen) 1038 1039 ; Read/write partial sector via deblocking code 1040 ; On Entry: 1041 ; FDRWSEC = sector address on disk 1042 ; FDRWSECOFF = offset within sector 1043 ; FDRWCNT = byte count for read/write 1044 ; On Exit: 1045 ; AX = # of bytes transferred 1046 1047 deblock_rw_npr: 0 0000B07B B90800 mov cx,BF_ISDAT ; CH = no preread, buffer is data 0 0000B07E EB03 jmp deblkrw05 1050 1051 deblock_rw: 1052 ;---------- 0 0000B080 B908FF mov cx,0FF00h+BF_ISDAT ; CH = preread, buffer is data 1054 deblkrw05: 0 0000B083 8B16[4900] mov dx,word ptr [fdrwsec] ; set sector to xfer from 1056 ; mov ah,byte ptr fdrwsec+WORD 0 0000B087 A1[4B00] mov ax,word ptr [fdrwsec+2] 0 0000B08A E8[0000] call locate_buffer ; ES:SI -> buffer 0 0000B08D 8B1E[4D00] mov bx,[fdrwsecoff] ; BX = offset within sector 0 0000B091 A1[0400] mov ax,[psecsiz] 0 0000B094 89C2 mov dx,ax ; DX = physical sector size 0 0000B096 29D8 sub ax,bx ; AX = bytes left in sector 0 0000B098 3B06[4300] cmp ax,[fdrwcnt] ; more than we want to transfer? 0 0000B09C 7203 jb deblkrw10 ; yes, only do up to end of sector 0 0000B09E A1[4300] mov ax,[fdrwcnt] ; else do up to end of request 1066 deblkrw10: 0 0000B0A1 89C1 mov cx,ax ; AX, CX = byte count 1068 ; (AX for return, CX for MOVSW) 0 0000B0A3 1E push ds 0 0000B0A4 F606[4200]01 test byte [fdrwflg],1 ; check if reading or writing 0 0000B0A9 740B jz dblkrw30 ; skip if writing 1072 0 0000B0AB 06 push es 0 0000B0AC C43E[4500] les di,[fdrwptr] ; destination is user memory 0 0000B0B0 1F pop ds ; source segment is data buffer 0 0000B0B1 8D7014 lea si,[BCB_DATA + si+bx] ; DS:SI -> data 0 0000B0B4 EB0C jmp dblkrw40 ; copy the data 1078 1079 dblkrw30: ; we're writing 0 0000B0B6 26804C0540 or byte [es:BCB_FLAGS + si],BF_DIRTY; mark buffer as dirty 0 0000B0BB 8D7814 lea di,[BCB_DATA + si+bx] ; ES:DI -> data 0 0000B0BE C536[4500] lds si,[fdrwptr] ; source is user memory 1083 1084 dblkrw40: 0 0000B0C2 D1E9 shr cx,1 ; make it a word count 0 0000B0C4 F3A5 rep movsw ; move the words 0 0000B0C6 7301 jnc dblkrw50 ; skip if even # of bytes 0 0000B0C8 A4 movsb ; else move last byte 1089 dblkrw50: 0 0000B0C9 1F pop ds ; restore registers 0 0000B0CA C3 ret 1092 1093 1094 ; entry: BYTEOFF = 32-bit offset into file 1095 ; BLKOFFSET = byte offset within cluster 1096 ; PRVBLK = block in which transfer starts 1097 ; FDRWREQ = requested transfer length 1098 1099 ;--------- 1100 direct_rw: 1101 ;--------- 0 0000B0CB 29D2 sub dx,dx ; assume no extra blocks required 0 0000B0CD A1[4000] mov ax,[fdrwreq] ; total byte count 0 0000B0D0 8B0E[2B00] mov cx,[clsize] ; get number of bytes 0 0000B0D4 8B1E[2D00] mov bx,[clsize+2] 0 0000B0D8 2B0E[7100] sub cx,[blkoffset] ; BX:CX = bytes remaining in this block 0 0000B0DC 1B1E[7300] sbb bx,[blkoffset+2] 0 0000B0E0 39DA cmp dx,bx 0 0000B0E2 7504 jne direct_rw03 0 0000B0E4 39C8 cmp ax,cx 0 0000B0E6 7428 je direct_rw10 1112 direct_rw03: 0 0000B0E8 29C8 sub ax,cx ; if wholly containined within block 0 0000B0EA 19DA sbb dx,bx 1115 ; jbe direct_rw10 ; then leave it alone 0 0000B0EC 7304 jnc direct_rw05 0 0000B0EE 31D2 xor dx,dx 0 0000B0F0 EB1E jmp direct_rw10 ; then leave it alone 1119 direct_rw05: 1120 ; div clsize ; else get # of extra clusters 1121 ; push cx 0 0000B0F2 52 push dx 0 0000B0F3 50 push ax 0 0000B0F4 FF36[2D00] push word [clsize+2] 0 0000B0F8 FF36[2B00] push word [clsize] 0 0000B0FC 83EC08 sub sp,8 0 0000B0FF E84805 call div32 0 0000B102 5A pop dx 0 0000B103 83C402 add sp,2 0 0000B106 58 pop ax 0 0000B107 83C40A add sp,10 1132 ; pop cx 0 0000B10A 92 xchg ax,dx ; DX = clusters, AX = remainder 0 0000B10B 09C0 or ax,ax ; round up if any remainder 0 0000B10D 7401 jz direct_rw10 ; skip if even number 0 0000B10F 42 inc dx ; else one more cluster 1137 direct_rw10: ; DX = # of contiguous clusters req'd 0 0000B110 E87400 call check_cont ; check how many contiguous blocks 1139 ; mov ax,clsize ; space = cnt * dpbptr->clsize; 1140 ; mul cx ; AX:DX = # of bytes transferrable 0 0000B113 FF36[2D00] push word [clsize+2] 0 0000B117 FF36[2B00] push word [clsize] 0 0000B11B 31C0 xor ax,ax 0 0000B11D 50 push ax 0 0000B11E 51 push cx 0 0000B11F 83EC08 sub sp,8 0 0000B122 E8E705 call mul32 0 0000B125 58 pop ax 0 0000B126 5A pop dx 0 0000B127 83C40C add sp,12 0 0000B12A 2B06[7100] sub ax,[blkoffset] ; BX = skipped bytes in 1st cluster 0 0000B12E 1B16[7300] sbb dx,[blkoffset+2] 1153 ; AX:DX = max # of bytes transferrable 1154 ; from current position 0 0000B132 85D2 test dx,dx 0 0000B134 7506 jnz direct_rw20 ; if > 64 K, use up request 0 0000B136 3B06[4000] cmp ax,[fdrwreq] ; if less than we requested 0 0000B13A 7205 jb direct_rw30 ; then lets do it 1159 direct_rw20: 0 0000B13C 31D2 xor dx,dx 0 0000B13E A1[4000] mov ax,[fdrwreq] ; else use requested count 1162 direct_rw30: 0 0000B141 F736[0400] div word [psecsiz] ; AX = # complete sectors 0 0000B145 A3[4F00] mov [fdrwdircnt],ax ; save direct sector count 0 0000B148 A3[3A00] mov [mult_sec],ax ; set multi sector count 0 0000B14B F726[0400] mul word [psecsiz] ; AX = bytes to xfer 0 0000B14F 50 push ax ; save for later 1168 0 0000B150 A1[4500] mov ax,[fdrwoff] ; FDRWPTR = disk transfer address 0 0000B153 A3[3C00] mov [cur_dma],ax 0 0000B156 A1[4700] mov ax,[fdrwseg] 0 0000B159 A3[3E00] mov [cur_dma_seg],ax 0 0000B15C A1[4900] mov ax,word ptr [fdrwsec] ; set sector to xfer from 0 0000B15F A3[3600] mov word ptr [pblock],ax 0 0000B162 A1[4B00] mov ax,word ptr [fdrwsec+2] 0 0000B165 A3[3800] mov word ptr [pblock+2],ax 0 0000B168 C606[0000]06 mov byte [rwmode],00000110b ;data read/write 0 0000B16D 8A0E[4200] mov cl,[fdrwflg] 0 0000B171 80E101 and cl,1 ; CL = read/write flag 0 0000B174 7407 jz direct_rw40 0 0000B176 31C9 xor cx,cx ; indicate no retries 0 0000B178 E81104 call read_block ; read in the data 0 0000B17B EB03 jmp direct_rw50 1184 direct_rw40: 0 0000B17D E8F803 call write_block ; write out the data 1186 direct_rw50: 0 0000B180 E83D00 call SynchroniseBuffers ; synchronize BCBs with direct transfer 0 0000B183 58 pop ax ; recover bytes xfered 0 0000B184 1E push ds 0 0000B185 07 pop es ; restore ES = SYSDAT 0 0000B186 C3 ret 1192 1193 1194 check_cont: ; check for adjacent blocks or space 1195 ;---------- 1196 ; entry: DX = # of extra contiguous blocks req'd 1197 ; exit: CX = # of contiguous blocks available 1198 1199 ; We first check all adjacent allocated clusters. 1200 ; If we'd like more and we find the end of file 1201 ; and we are writing and the adjacent blocks aren't 1202 ; allocated, then we count them as well and link 1203 ; them into the file. 1204 0 0000B187 89D7 mov di,dx ; save # of blocks req'd 0 0000B189 A1[6900] mov ax,[blk] ; current block number 0 0000B18C 8B16[6B00] mov dx,[blk+2] 0 0000B190 31C9 xor cx,cx ; contiguous blocks found = 0 0 0000B192 85FF test di,di ; any extra required ? 0 0000B194 7428 jz check_cont20 1211 check_cont10: ; get link of current block 1212 ; push ax ; save current block 0 0000B196 A3[8100] mov [check_cont_cl],ax ; save current block 0 0000B199 8916[8300] mov [check_cont_cl+2],dx 0 0000B19D 51 push cx ; save extra blocks so far 0 0000B19E 57 push di ; save extra blocks we'd like 0 0000B19F E8[0000] call getnblk ; get the link 0 0000B1A2 5F pop di 0 0000B1A3 59 pop cx 1220 ; pop bx 1221 ; inc bx ; BX = current block + 1 0 0000B1A4 8306[8100]01 add word [check_cont_cl],1 ; current block + 1 0 0000B1A9 8316[8300]00 adc word [check_cont_cl+2],0 1224 ; cmp ax,bx ; check if next block is contiguous 0 0000B1AE 3B06[8100] cmp ax,[check_cont_cl] ; check if next block is contiguous 0 0000B1B2 750A jne check_cont20 ; and try for another 0 0000B1B4 3B16[8300] cmp dx,[check_cont_cl+2] 0 0000B1B8 7504 jne check_cont20 0 0000B1BA 41 inc cx ; extra contiguous cluster 0 0000B1BB 4F dec di ; one less block to check 0 0000B1BC 75D8 jnz check_cont10 ; try again if we still want more 1232 check_cont20: ; we can do CX extra clusters 0 0000B1BE 41 inc cx ; include 1st cluster too.. 0 0000B1BF C3 ret 1235 1236 1237 ;------------------ 1238 SynchroniseBuffers: ; synchronize BCBs after multi sector transfer 1239 ;------------------ 1240 ; On Entry: 1241 ; FDRWSEG:FDRWOFF = transfer address for IO_READ/IO_WRITE 1242 ; FDRWDIRCNT = physical sector count for direct transfer 1243 ; FDRWSEC = sector address for transfer 1244 ; FDWRFLG = even for write, odd for read 1245 ; On Exit: 1246 ; direct transfer buffer or BCB updated if BCB overlap 1247 ; 1248 ; If any data buffer is found, that falls into the region affected 1249 ; by the direct sector transfer, the following action is performed: 1250 ; If the operation was a read and the sector buffer is clean, 1251 ; no action is required. If it was dirty, the buffer contents is 1252 ; copied to the corresponding location in the DTA buffer. 1253 ; If the operation was a write, the sector buffer is discarded. 1254 ; 1255 ; 0 0000B1C0 8B16[4900] mov dx,word ptr [fdrwsec] 1257 ; mov ah,byte ptr fdrwsec+WORD 0 0000B1C4 A1[4B00] mov ax,word ptr [fdrwsec+2] 1259 ; mov al,adrive ; get our drive number 0 0000B1C7 8A0E[3500] mov cl,[adrive] ; get our drive number 0 0000B1CB C51E[0000] lds bx,[bcb_root] ; DS:BX -> 1st buffer 1262 SynchroniseBuffers10: 0 0000B1CF F6470508 test byte [BCB_FLAGS + bx],BF_ISDAT; is this a data buffer? 0 0000B1D3 744C jz SynchroniseBuffers30 ; skip if directory or FAT 1265 ; cmp al,ds:BCB_DRV[bx] ; does the drive match? 0 0000B1D5 3A4F04 cmp cl,[BCB_DRV + bx] ; does the drive match? 0 0000B1D8 7547 jne SynchroniseBuffers30 ; skip if different 0 0000B1DA 8B7706 mov si,[BCB_REC + bx] ; compute bcb->rec - prec 0 0000B1DD 29D6 sub si,dx ; result in SI,DI (lsb..msb) 1270 ; mov cl,ds:byte ptr BCB_REC2[bx] 1271 ; sbb cl,ah ; get bits 16-23 of result 0 0000B1DF 8B7F08 mov di,[BCB_REC2 + bx] 0 0000B1E2 19C7 sbb di,ax ; get bits 16-31 of result 0 0000B1E4 753B jne SynchroniseBuffers30 ; skip if bcb->rec < prec 0 0000B1E6 363B36[4F00] cmp si,[ss:fdrwdircnt] ; else check against transfer length 0 0000B1EB 7334 jae SynchroniseBuffers30 ; skip if beyond transfer length 1277 0 0000B1ED 36F606[4200]01 test byte [ss:fdrwflg],1 ; test direction: read or write 0 0000B1F3 7428 jz SynchroniseBuffers20 ; skip if disk write 1280 0 0000B1F5 F6470540 test byte [BCB_FLAGS + bx],BF_DIRTY; if buffer dirty, did read old data 0 0000B1F9 7426 jz SynchroniseBuffers30 ; else data read was valid 1283 0 0000B1FB 50 push ax 0 0000B1FC 52 push dx ; save record address 1286 0 0000B1FD 36A1[0400] mov ax,[ss:psecsiz] ; # of bytes in sector buffer 0 0000B201 51 push cx ; save drive number 0 0000B202 89C1 mov cx,ax 0 0000B204 D1E9 shr cx,1 ; CX = words per sector 0 0000B206 F7E6 mul si ; AX = byte offset from start buffer 0 0000B208 360306[4500] add ax,[ss:fdrwoff] ; AX = offset 0 0000B20D 97 xchg ax,di ; DI = offset 0 0000B20E 368E06[4700] mov es,[ss:fdrwseg] ; ES:DI -> data to be replaced 0 0000B213 8D7714 lea si,[BCB_DATA + bx] 0 0000B216 F3A5 rep movsw ; move CX words (one physical sector) 0 0000B218 59 pop cx ; restore drive number 0 0000B219 5A pop dx 0 0000B21A 58 pop ax ; restore record address 0 0000B21B EB04 jmp SynchroniseBuffers30 1301 1302 SynchroniseBuffers20: ; multi sector write 0 0000B21D C64704FF mov byte [BCB_DRV + bx],0FFh ; discard this sector 1304 SynchroniseBuffers30: 0 0000B221 8B1F mov bx,[BCB_NEXT + bx] 0 0000B223 363B1E[0000] cmp bx,word ptr [ss:bcb_root] 0 0000B228 75A5 jne SynchroniseBuffers10 ; if so stop 0 0000B22A 16 push ss 0 0000B22B 1F pop ds ; restore DS 0 0000B22C C3 ret 1311 1312 Public blockif, ddioif 1313 1314 ;======= ================================ 1315 blockif: ; disk read/write bios interface 1316 ;======= ================================ 1317 ; entry: AL = BIOS Request function number 1318 ; ADRIVE = block device to xfer to/from 1319 ; RWMODE = read/write mode 1320 ; CUR_DMA_SEG:CUR_DMA -> xfer address 1321 ; PBLOCK = starting block of xfer 1322 ; MULT_CNT = # blocks to xfer 1323 ; exit: AX = BX = output 1324 0 0000B22D A2[C100] mov [req_cmd],al 0 0000B230 A0[0000] mov al,[rwmode] ; copy rwmode to where the device 0 0000B233 A2[C400] mov [req_rwmode],al ; driver can get the hint 0 0000B236 A1[3C00] mov ax,[cur_dma] ; get DMA offset 0 0000B239 50 push ax ; (save it) 0 0000B23A 83E00F and ax,000Fh ; get offset within paragraph 0 0000B23D A3[CD00] mov [req4_buffer],ax ; set transfer offset 0 0000B240 58 pop ax ; (restore offset) 0 0000B241 B104 mov cl,4 0 0000B243 D3E8 shr ax,cl ; convert to paragraphs 0 0000B245 0306[3E00] add ax,[cur_dma_seg] ; add in the segment 0 0000B249 A3[CF00] mov [req4_buffer+2],ax ; set transfer segment 0 0000B24C A1[3A00] mov ax,[mult_sec] ; get requested sector count 0 0000B24F A3[D100] mov [req4_count],ax ; set requested sector count 1339 ;------ 1340 ddioif: 1341 ;------ 0 0000B252 06 push es 0 0000B253 A0[3500] mov al,[adrive] ; get selected drive 0 0000B256 E86AF8 call get_ddsc ; ES:BX -> DDSC 0 0000B259 A1[3600] mov ax,word ptr [pblock] 0 0000B25C 8B16[3800] mov dx,word ptr [pblock+2] ; DX:AX = starting block 0 0000B260 06 push es 0 0000B261 26C47713 les si,[es:DDSC_DEVHEAD + bx] ; ES:SI -> device driver 1349 ; DOS 4 support 0 0000B265 A3[D900] mov word ptr [req4_bigsector],ax 0 0000B268 8916[DB00] mov word ptr [req4_bigsector+2],dx 0 0000B26C C606[BF00]1E mov byte [req_len],RH4_LEN ; set length of request header 1353 DEVHDR.ATTRIB equ ATTRIB ; NASM port label 0 0000B271 26F744040200 test word [es:DEVHDR.ATTRIB + si],DA_BIGDRV ; large sector number support? 0 0000B277 7403 jz blockif10 ; no, normal request header 0 0000B279 B8FFFF mov ax,-1 ; indicate we use 32-bit sector number 1357 blockif10: 0 0000B27C A3[D300] mov [req4_sector],ax ; set requested sector address 0 0000B27F 07 pop es 1360 0 0000B280 E80E00 call block_device_driver ; make call to device driver 0 0000B283 7802 js blockif20 0 0000B285 31C0 xor ax,ax ; no error 1364 blockif20: 0 0000B287 C706[3A00]0100 mov word [mult_sec],1 ; reset sector count 0 0000B28D 89C3 mov bx,ax ; AX, BX = return code 0 0000B28F 07 pop es 0 0000B290 C3 ret 1369 1370 1371 1372 block_device_driver: 1373 ;------------------ 1374 ; entry: ES:BX -> DDSC, req_hdr partly filled in 1375 ; exit: AX = status after function 1376 ; SF = 1 if error occurred 1377 ; note: BX preserved 1378 0 0000B291 268A4717 mov al,[es:DDSC_MEDIA + bx] 0 0000B295 A2[CC00] mov [req_media],al ; set current media byte 0 0000B298 268A4701 mov al,[es:DDSC_RUNIT + bx] ; get relative unit # 0 0000B29C A2[C000] mov [req_unit],al ; set the unit 0 0000B29F 1E push ds 0 0000B2A0 06 push es 0 0000B2A1 53 push bx 0 0000B2A2 1E push ds 0 0000B2A3 26C57713 lds si,[es:DDSC_DEVHEAD + bx] 0 0000B2A7 07 pop es 0 0000B2A8 BB[BF00] mov bx,offset req_hdr ; ES:BX -> request packet 0 0000B2AB E80400 call device_driver ; do operation 0 0000B2AE 5B pop bx 0 0000B2AF 07 pop es 0 0000B2B0 1F pop ds 0 0000B2B1 C3 ret 1395 1396 ; On Entry: 1397 ; DS:SI Device Header 1398 ; ES:BX Current Request Header 1399 ; 1400 ; On Exit: 1401 ; AX Request Header Status 1402 ; 1403 device_driver: 1404 ;------------ 0 0000B2B2 31C0 xor ax,ax 0 0000B2B4 26894703 mov [es:RH_STATUS + bx],ax ; Initialise return status 0 0000B2B8 06 push es 0 0000B2B9 53 push bx 0 0000B2BA 55 push bp 0 0000B2BB 36FF1E[0000] call far [ss:lock_bios] ; lock access to BIOS 0 0000B2C0 0E push cs 0 0000B2C1 E81100 call device_driver10 ; fake a callf 0 0000B2C4 36FF1E[0000] call far [ss:unlock_bios] ; unlock access to BIOS 0 0000B2C9 5D pop bp 0 0000B2CA 5B pop bx 0 0000B2CB 07 pop es 0 0000B2CC FB sti 0 0000B2CD FC cld ; Restore Flags 0 0000B2CE 268B4703 mov ax,[es:RH_STATUS + bx] ; Return the Status to the caller 0 0000B2D2 85C0 test ax,ax ; set SF=1 if error 0 0000B2D4 C3 ret 1422 1423 device_driver10: 1424 ; push ds 1425 ; push ds:DH_INTERRUPT[si] ; interrupt routine address on stack 1426 ; push ds 1427 ; push ds:DH_STRATEGY[si] ; strategy routine address on stack 1428 ; retf ; retf to strategy, interrupt, us 0 0000B2D5 1E push ds 0 0000B2D6 56 push si 0 0000B2D7 0E push cs 0 0000B2D8 B8[1E08] mov ax,offset device_driver11 0 0000B2DB 50 push ax 0 0000B2DC 1E push ds 1435 DEVHDR.STRATEGY equ STRATEGY ; NASM port label 0 0000B2DD FF7406 push word [DEVHDR.STRATEGY + si] ; strategy routine address on stack 0 0000B2E0 CB retf ; retf to strategy and device_driver11 1438 device_driver11: 0 0000B2E1 5E pop si 0 0000B2E2 1F pop ds 0 0000B2E3 1E push ds 1442 DEVHDR.INTERRUPT equ INTERRUPT ; NASM port label 0 0000B2E4 FF7408 push word [DEVHDR.INTERRUPT + si] ; interrupt routine address on stack 0 0000B2E7 CB retf ; retf to interrupt, us 1445 1446 ; Select drive and check for door open ints 1447 ; Build fdos_hds to refer to the drive 1448 1449 ; Exit: DL = drive to be selected (0-15) 1450 1451 select_logical_drv: 1452 ;------------------ 1453 ; On Entry: 1454 ; AL = logical drive to select (with change media checks) 1455 ; On Exit: 1456 ; ES:BX -> LDT_ 1457 ; 0 0000B2E8 3A06[0000] cmp al,[last_drv] ; is it a legal drive ? 1459 ; jae select_drv_bad ; no, reject it now 0 0000B2EC 7203 jb select_logical_drv05 0 0000B2EE E99100 jmp select_drv_bad ; no, reject it now 1462 select_logical_drv05: 0 0000B2F1 A2[0200] mov [logical_drv],al ; save logical drive 0 0000B2F4 E8[0000] call get_ldt ; ES:BX -> LDT_ for drive 0 0000B2F7 7265 jc select_physical_drv ; no LDT_ during init, must be physical 0 0000B2F9 891E[0000] mov word ptr [current_ldt],bx 0 0000B2FD 8C06[0200] mov word ptr [current_ldt+2],es 0 0000B301 268A4744 mov al,byte ptr [es:LDT_FLAGS+1 + bx] ; is the drive valid ? 1469 ; test al,(LFLG_NETWRKD+LFLG_JOINED)/100h 1470 ; jnz select_drv_bad ; reject networked/joined drives 0 0000B305 A820 test al,LFLG_JOINED/100h 0 0000B307 7579 jnz select_drv_bad ; reject joined drives 0 0000B309 A840 test al,LFLG_PHYSICAL/100h 0 0000B30B 7475 jz select_drv_bad ; reject non-physical drives 0 0000B30D A880 test al,LFLG_NETWRKD/100h ; skip if networked drive 0 0000B30F 754C jnz select_logical_drv30 0 0000B311 268A07 mov al,[es:LDT_NAME + bx] ; get the drive from the ascii name 0 0000B314 241F and al,1fh ; as the drive may require rebuilding 0 0000B316 48 dec ax ; make it zero based 0 0000B317 06 push es 0 0000B318 53 push bx 0 0000B319 E84200 call select_physical_drv ; select the physical root 0 0000B31C 5B pop bx 0 0000B31D 07 pop es 0 0000B31E 26837F4F02 cmp word [es:LDT_ROOTLEN + bx],2 ; if logical and physical roots 0 0000B323 7638 jbe select_logical_drv30 ; are the same we are OK now 1487 %ifdef JOIN 0 0000B325 268A474D mov al,[es:LDT_DRV + bx] ; should we be on a different 0 0000B329 3A06[0000] cmp al,[fdos_hds_drv] ; physical drive ? 0 0000B32D 750E jne select_logical_drv10 ; if so then we'd better rebuild 1491 %endif 0 0000B32F 26837F49FF cmp word [es:LDT_BLK + bx],0FFFFh ; did we have a media change ? 0 0000B334 750A jne select_logical_drv20 ; then we'd better rebuild 0 0000B336 26837F51FF cmp word [es:LDT_BLKH + bx],0FFFFh 0 0000B33B 7503 jne select_logical_drv20 1496 select_logical_drv10: 0 0000B33D E8[0000] call rebuild_ldt_root ; the LDT_ root block 1498 select_logical_drv20: 0 0000B340 268B474B mov ax,[es:LDT_ROOT + bx] ; get virtual root from LDT 0 0000B344 268B5753 mov dx,[es:LDT_ROOTH + bx] 0 0000B348 A3[0000] mov [fdos_hds_root],ax ; move there 0 0000B34B 8916[0200] mov [fdos_hds_root+2],dx 0 0000B34F A3[0000] mov [fdos_hds_blk],ax 0 0000B352 8916[0200] mov [fdos_hds_blk+2],dx 1505 %ifdef JOIN 0 0000B356 268A474D mov al,[es:LDT_DRV + bx] ; same with drive 0 0000B35A A2[0000] mov [fdos_hds_drv],al 1508 %endif 1509 select_logical_drv30: 0 0000B35D C3 ret 1511 1512 select_physical_drv: 1513 ;------------------- 1514 ; On Entry: 1515 ; AL = physical drive to select (with change media checks) 1516 ; On Exit: 1517 ; None 1518 ; 0 0000B35E 31D2 xor dx,dx 0 0000B360 8916[0000] mov [fdos_hds_blk],dx ; put it in the root by default 0 0000B364 8916[0200] mov [fdos_hds_blk+2],dx 0 0000B368 8916[0000] mov [fdos_hds_root],dx 0 0000B36C 8916[0200] mov [fdos_hds_root+2],dx 0 0000B370 A2[0000] mov [fdos_hds_drv],al ; set physical drive in working HDS 0 0000B373 3A06[0000] cmp al,[phys_drv] ; should we have a DDSC_ for this drive 0 0000B377 7309 jae select_drv_bad ; no, we can't select it then 0 0000B379 A2[0300] mov [physical_drv],al ; save physical drive number 0 0000B37C E80C00 call select_adrive ; no, better select it 0 0000B37F 7207 jc select_drv_critical_error 0 0000B381 C3 ret 1531 1532 select_drv_bad: 1533 ;-------------- 1534 ; An attempt has been made to select a bad drive, 1535 ; return a logical error "invalid drive" 0 0000B382 B8F1FF mov ax,ED_DRIVE ; ED_DRIVE "invalid drive" 0 0000B385 E9[0000] jmp fdos_error 1538 1539 select_drv_critical_error: 1540 ;------------------------- 1541 ; The drive is logically correct, so all error at this point must 1542 ; be physical ones - so we want a critical error 0 0000B388 E92E02 jmp generate_critical_error 1544 1545 select_adrive: 1546 ;------------- 1547 ; This entry is called to physically select a drive (eg. when flushing buffers) 1548 ; It does not alter the current physical_drv setting, which must be re-selected 1549 ; afterwards by the caller. 1550 ; 1551 ; On Entry: 1552 ; AL = disk to select (range validated) 1553 ; On Exit: 1554 ; CY set if a problem selecting the drive 1555 0 0000B38B A2[3500] mov [adrive],al 0 0000B38E A2[0000] mov [err_drv],al ; save error drive 0 0000B391 E82FF7 call get_ddsc ; ES:BX -> DDSC_ for drive 0 0000B394 B001 mov al,1 ; AL = "Unknown Unit" 0 0000B396 7232 jc select_drv_err ; error if no DDSC_ 0 0000B398 268B4713 mov ax,word ptr [es:DDSC_DEVHEAD + bx] 0 0000B39C A3[0000] mov word ptr [error_dev+0],ax 0 0000B39F 268B4715 mov ax,word ptr [es:DDSC_DEVHEAD+2 + bx] 0 0000B3A3 A3[0200] mov word ptr [error_dev+2],ax 0 0000B3A6 06 push es ; remember driver address for error's 0 0000B3A7 53 push bx ; preserve DDSC_ 0 0000B3A8 E85E01 call check_media ; see if media has changed 0 0000B3AB 5B pop bx ; restore DDSC_ 0 0000B3AC 07 pop es 0 0000B3AD 721B jc select_drv_err 1571 1572 ; select the disk drive and fill the drive specific variables 1573 ; entry: ES:BX -> DDSC_ of disk to select 1574 ; AX <> 0 if drive requires BPB rebuilt 1575 ; exit: CY flag set on error 1576 0 0000B3AF 85C0 test ax,ax ; device driver, new select? 0 0000B3B1 741B jz select_ddsc ; use current DDSC if old select 0 0000B3B3 E8CB00 call build_ddsc_from_bpb ; else get BPB and build new DDSC 0 0000B3B6 7212 jc select_drv_err ; carry flag reset 0 0000B3B8 E81300 call select_ddsc ; use to DDSC for select 1582 %ifdef DELWATCH 0 0000B3BB B407 mov ah,DELW_NEWDISK ; we have a new disk so I guess 0 0000B3BD A0[0300] mov al,[physical_drv] ; I'd better tell delwatch 0 0000B3C0 C41E[0000] les bx,[current_ddsc] ; about the new disk so it 0 0000B3C4 FF1E[0000] call far [fdos_stub] ; knows to update itself 1587 %endif 0 0000B3C8 F8 clc ;select disk function ok 0 0000B3C9 C3 ret 1590 1591 select_drv_err: 1592 ; On Entry: 1593 ; AL = extended error code 1594 ; CY set 1595 ; 0 0000B3CA A2[0000] mov [ioexerr],al ; save error code 0 0000B3CD C3 ret 1598 1599 1600 select_ddsc: 1601 ;----------- 1602 ; On Entry: 1603 ; ES:BX -> DDSC_ of drive to be selected 0 0000B3CE 891E[0000] mov word ptr [current_ddsc],bx 0 0000B3D2 8C06[0200] mov word ptr [current_ddsc+2],es 0 0000B3D6 1E push ds 0 0000B3D7 06 push es 0 0000B3D8 1F pop ds 0 0000B3D9 07 pop es ; swap ES and DS 0 0000B3DA 8D7702 lea si,[DDSC_SECSIZE + bx] ; DS:SI -> DDSC_ original 0 0000B3DD BF[0400] mov di,offset local_ddsc ; ES:DI -> DDSC_ copy 0 0000B3E0 B91100 mov cx,LOCAL_DDSC_LEN 0 0000B3E3 F3A4 rep movsb ; make a local copy of interesting bits 0 0000B3E5 837F0F00 cmp word [DDSC_NFATRECS + bx],0 ; is it a 32 bit FAT ? 0 0000B3E9 741C je select_ddsc04 ; yes, then also copy extended DDSC 0 0000B3EB 26A1[0D00] mov ax,[es:datadd] ; these values are used as 32-bit 0 0000B3EF 26A3[1500] mov [es:bdatadd],ax 0 0000B3F3 26A1[0F00] mov ax,[es:lastcl] 0 0000B3F7 26A3[1900] mov [es:blastcl],ax 0 0000B3FB 31C0 xor ax,ax 0 0000B3FD 26A3[1700] mov [es:bdatadd+2],ax 0 0000B401 26A3[1B00] mov [es:blastcl+2],ax 0 0000B405 EB0B jmp select_ddsc05 1624 select_ddsc04: 0 0000B407 8D772B lea si,[DDSC_BDATADDR + bx] 0 0000B40A BF[1500] mov di,offset local_ddsc2 0 0000B40D B91000 mov cx,LOCAL_DDSC2_LEN 0 0000B410 F3A4 rep movsb ; more interesting bits to copy 1629 select_ddsc05: 1630 ; push es ! pop ds ; DS=ES=local data segment 0 0000B412 1E push ds 0 0000B413 06 push es 0 0000B414 1F pop ds 0 0000B415 07 pop es ; swap ES and DS 1635 ; mov ax,psecsiz ; now initialise some other vaiiables 1636 ; mov cl,clshf 1637 ; shl ax,cl ; AX = bytes per cluster 1638 ; mov clsize,ax 0 0000B416 31C0 xor ax,ax 0 0000B418 A0[0600] mov al,[clmsk] 0 0000B41B 40 inc ax ; AX = sectors per cluster 0 0000B41C A3[2F00] mov [secperclu],ax 0 0000B41F F726[0400] mul word [psecsiz] ; DX:AX byte size of cluster 0 0000B423 A3[2B00] mov [clsize],ax 0 0000B426 8916[2D00] mov [clsize+2],dx 0 0000B42A 31C0 xor ax,ax 0 0000B42C A0[0A00] mov al,[byte_nfats] ; AX = number of FATs 0 0000B42F A3[2500] mov [nfats],ax ; (it's handier as a word 1649 ; mov ax,diradd ; number of FAT records can be 1650 ; sub ax,fatadd ; bigger than 255 1651 ; xor dx,dx 1652 ; div nfats 0 0000B432 26837F0F00 cmp word [es:DDSC_NFATRECS + bx],0 ; is it a 32 bit FAT ? 0 0000B437 740E je select_ddsc10 ; yes, then use 32-bit value 0 0000B439 268B470F mov ax,word ptr [es:DDSC_NFATRECS + bx] ; # of sectors per FAT 0 0000B43D A3[2700] mov [nfatrecs],ax 0 0000B440 31C0 xor ax,ax 0 0000B442 A3[2900] mov [nfatrecs+2],ax 0 0000B445 EB0E jmp select_ddsc20 1660 select_ddsc10: 0 0000B447 268B4733 mov ax,word ptr [es:DDSC_BFATRECS + bx] ; # of sectors per FAT 0 0000B44B A3[2700] mov [nfatrecs],ax 0 0000B44E 268B4735 mov ax,word ptr [es:DDSC_BFATRECS+2 + bx] 0 0000B452 A3[2900] mov [nfatrecs+2],ax 1665 select_ddsc20: 0 0000B455 B92000 mov cx,FCBLEN 0 0000B458 A1[2B00] mov ax,[clsize] ; convert from cluster size 1668 ; xor dx,dx ; to number of dir entries 0 0000B45B 8B16[2D00] mov dx,[clsize+2] ; to number of dir entries 0 0000B45F F7F1 div cx ; per cluster - handy for 0 0000B461 A3[3100] mov [dirperclu],ax ; subdirectories 0 0000B464 B80000 mov ax,FAT32 0 0000B467 26837F0F00 cmp word [es:DDSC_NFATRECS + bx],0 ; is it a 32 bit FAT ? 0 0000B46C 740E je select_ddsc30 0 0000B46E B8FF0F mov ax,FAT12 0 0000B471 813E[0F00]F60F cmp word [lastcl],MAX12 ; is it a 12 bit FAT ? 0 0000B477 7603 jbe select_ddsc30 0 0000B479 B8FFFF mov ax,FAT16 ; no, it's 16 bit 1679 select_ddsc30: 0 0000B47C A3[3300] mov [dosfat],ax ; remember which for later 0 0000B47F F8 clc ; drive all selected 0 0000B480 C3 ret 1683 1684 1685 1686 1687 1688 build_ddsc_from_bpb: ; call device driver to build BPB, convert to DDSC_ 1689 ;------------------- 1690 ; On Entry: 1691 ; ES:BX -> DDSC_ to rebuild 1692 ; On Exit: 1693 ; ES:BX preserved 1694 ; CY set on error 1695 ; AL = error code 1696 0 0000B481 06 push es 0 0000B482 53 push bx ; save DDSC_ address 0 0000B483 31FF xor di,di 0 0000B485 A1[0000] mov ax,[deblock_seg] 0 0000B488 8EC0 mov es,ax ; ES:DI -> deblock seg 0 0000B48A 85C0 test ax,ax ; if we are deblocking spare buffer 0 0000B48C 7511 jnz build_bpb10 ; might be in high memory 0 0000B48E 48 dec ax ; AX = FFFF 0 0000B48F 89C2 mov dx,ax ; compute impossible record # 0 0000B491 B90400 mov cx,BF_ISDIR ; locate directory sector w/o preread 0 0000B494 E8[0000] call locate_buffer ; this will find the cheapest buffer 0 0000B497 26C64404FF mov byte [es:BCB_DRV + si],0FFh ; don't really want this... 0 0000B49C 8D7C14 lea di,[BCB_DATA + si] ; ES:DI -> disk buffer 1710 build_bpb10: 0 0000B49F 893E[CD00] mov [req4_buffer],di ; xfer to ES:DI 0 0000B4A3 8C06[CF00] mov [req4_buffer+2],es 0 0000B4A7 5B pop bx ; restore DDSC_ address 0 0000B4A8 07 pop es 1715 0 0000B4A9 1E push ds 0 0000B4AA 26C57713 lds si,[es:DDSC_DEVHEAD + bx] ; DS:SI -> device header 0 0000B4AE 8B4404 mov ax,[DEVHDR.ATTRIB + si] ; non-FAT ID driver ("non-IBM") bit 0 0000B4B1 1F pop ds ; in device header attributes 0 0000B4B2 A90020 test ax,DA_NONIBM 0 0000B4B5 7530 jnz bldbpb30 ; skip if media byte in FAT not used 1722 0 0000B4B7 C606[C400]00 mov byte [req_rwmode],0 ; read of system area 0 0000B4BC C606[BF00]1E mov byte [req_len],RH4_LEN ; set length field 0 0000B4C1 C606[C100]04 mov byte [req_cmd],CMD_INPUT ; read first FAT sector off disk 0 0000B4C6 A90200 test ax,DA_BIGDRV ; large sector numbers ? 0 0000B4C9 B80100 mov ax,1 0 0000B4CC A3[D100] mov [req4_count],ax ; read 1st FAT sector 0 0000B4CF 99 cwd ; DS:AX = sector 1 0 0000B4D0 A3[D900] mov word ptr [req4_bigsector],ax 0 0000B4D3 8916[DB00] mov word ptr [req4_bigsector+2],dx 0 0000B4D7 7402 jz bldbpb20 0 0000B4D9 48 dec ax 0 0000B4DA 48 dec ax ; AX = 0FFFFh 1735 bldbpb20: 0 0000B4DB A3[D300] mov [req4_sector],ax ; set requested sector address 0 0000B4DE 8916[D500] mov [req4_sector+2],dx ; (support large DOS drives) 0 0000B4E2 E8ACFD call block_device_driver ; try to read FAT sector, AX = status 0 0000B4E5 7820 js bldbpb_err ; skip if errors (AX negative) 1740 bldbpb30: 0 0000B4E7 C606[BF00]18 mov byte [req_len],RH2_LEN ; length of req 0 0000B4EC C606[C100]02 mov byte [req_cmd],CMD_BUILD_BPB ; "build bpb" 0 0000B4F1 E89DFD call block_device_driver ; call the device driver 0 0000B4F4 7811 js bldbpb_err ; skip if errors (AX negative) 0 0000B4F6 1E push ds 0 0000B4F7 06 push es 0 0000B4F8 53 push bx 0 0000B4F9 89DF mov di,bx ; ES:DI -> DDSC_ to initialise 0 0000B4FB C536[D100] lds si,[req2_bpb] ; DS:SI -> BPB to convert 0 0000B4FF E8[0000] call bpb2ddsc ; rebuild the DDSC_ 0 0000B502 5B pop bx 0 0000B503 07 pop es 0 0000B504 1F pop ds 0 0000B505 F8 clc ; success - we have a new DDSC_ 0 0000B506 C3 ret 1756 1757 1758 bldbpb_err: 0 0000B507 F9 stc ; we had a problem 0 0000B508 C3 ret 1761 1762 1763 1764 ;----------- 1765 check_media: ; check media if DPH media flag set 1766 ;----------- 1767 ; On Entry: 1768 ; ES:BX -> DDSC_ of physical drive to check 1769 ; On Exit: 1770 ; CY set on error, AX = error code 1771 ; else 1772 ; AX <> 0 if disk requires BPB rebuild 1773 ; If definite/possible change then LDT's marked as invalid 1774 ; If possible then buffers/hashing discarded provided they are clean 1775 ; If definite then all buffers/hashing for drive discarded even if dirty 1776 ; 0 0000B509 C606[BF00]0F mov byte [req_len],RH1_LEN ; set length field 0 0000B50E C606[C100]01 mov byte [req_cmd],CMD_MEDIA_CHECK ; media check routine 0 0000B513 E87BFD call block_device_driver ; call the device driver 0 0000B516 7902 jns chkmed10 0 0000B518 F9 stc ; we have a problem, generate 0 0000B519 C3 ret ; an error 1783 chkmed10: 0 0000B51A A0[CD00] mov al,[req_media+1] ; else get returned value 0 0000B51D 30E4 xor ah,ah ; watch out for 1st access too.. 0 0000B51F 26866718 xchg ah,[es:DDSC_FIRST + bx] ; treat never accessed as changed 0 0000B523 3C01 cmp al,1 ; 1 = no change 0 0000B525 7502 jne chkmed20 0 0000B527 48 dec ax ; AL=0, build bpb only if DDSC_FIRST 1790 ; clc ; it all went OK 0 0000B528 C3 ret 1792 1793 chkmed20: 0 0000B529 8A16[3500] mov dl,[adrive] ; media may have/has changed 0 0000B52D E81D00 call mark_ldt_unsure ; so force LDT's to unsure 1796 1797 ; AL = 00 if maybe changed, FF for definitely changed 0 0000B530 84C0 test al,al 0 0000B532 7405 jz chkmed_maybe ; media may have changed 1800 1801 chkmed_changed: ; disk has changed for sure 0 0000B534 E8[0000] call discard_files ; discard open files 0 0000B537 EB0D jmp chkmed30 ; discard buffers, build bpb required 1804 1805 chkmed_maybe: ; disk has possibly changed 0 0000B539 E8[0000] call discard_dir ; we can always discard dir as they 0 0000B53C B440 mov ah,BF_DIRTY ; won't be dirty 0 0000B53E A0[3500] mov al,[adrive] 0 0000B541 E8[0000] call buffers_check ; any dirty buffers on adrive? 0 0000B544 7503 jnz chkmed40 ; yes, can't discard FAT 1811 chkmed30: 0 0000B546 E8[0000] call discard_all ; discard buffers for drive 1813 chkmed40: 0 0000B549 83C8FF or ax,0FFFFh ; better rebuild bpb 1815 ; clc 0 0000B54C C3 ret 1817 1818 1819 Public mark_ldt_unsure 1820 1821 mark_ldt_unsure: 1822 ;--------------- 1823 ; On Entry: 1824 ; DL = physical drive 1825 ; On Exit: 1826 ; All corresponding LDT's marked as unsure 1827 ; All reg preserved 1828 ; 0 0000B54D 06 push es 0 0000B54E 50 push ax 0 0000B54F 53 push bx 0 0000B550 31C0 xor ax,ax ; start with drive A: 1833 mlu10: 0 0000B552 E8[0000] call get_ldt_raw ; ES:BX -> LDT_ 0 0000B555 721D jc mlu30 ; CY = no more LDT's 0 0000B557 26F7474300A0 test word [es:LDT_FLAGS + bx],LFLG_NETWRKD+LFLG_JOINED 0 0000B55D 7512 jnz mlu20 ; if networked leave it alone 0 0000B55F 263A574D cmp dl,[es:LDT_DRV + bx] ; does the physical drive match ? 0 0000B563 750C jne mlu20 0 0000B565 26C74749FFFF mov word [es:LDT_BLK + bx],0FFFFh ; indicate we shouldn't trust BLK 0 0000B56B 26C74751FFFF mov word [es:LDT_BLKH + bx],0FFFFh 1842 mlu20: 0 0000B571 40 inc ax ; onto next LDT 0 0000B572 EBDE jmp mlu10 1845 mlu30: 0 0000B574 5B pop bx 0 0000B575 58 pop ax 0 0000B576 07 pop es 0 0000B577 C3 ret 1850 1851 ;----------- 1852 write_block: 1853 ;----------- 1854 ; entry: RWMODE = write type 1855 ; bit 0: 1856 ; 1 - write, not read 1857 ; bits 2-1 (affected disk area) 1858 ; 0 0 - system area 1859 ; 0 1 - FAT area 1860 ; 1 0 - root or sub directory 1861 ; 1 1 - data area 1862 0 0000B578 800E[0000]01 or byte [rwmode],1 ; mark it as a write 0 0000B57D 31C9 xor cx,cx ; indicate no second attempt 0 0000B57F B008 mov al,CMD_OUTPUT ; assume normal write 0 0000B581 803E[0000]00 cmp byte [verify_flag],0 ; is verify on ? 0 0000B586 740B je rdwr_block 0 0000B588 B009 mov al,CMD_OUTPUT_VERIFY ; assume use write w/ verify 0 0000B58A EB07 jmp rdwr_block 1870 1871 ;---------- 1872 read_block: 1873 ;---------- 1874 ; entry: RWMODE = read type 1875 ; bit 0: 1876 ; 0 - read, not write 1877 ; bits 2-1 (affected disk area) 1878 ; 0 0 - system area 1879 ; 0 1 - FAT area 1880 ; 1 0 - root or sub directory 1881 ; 1 1 - data area 1882 ; CX <> 0 if FAT retry possible (critical error should then 1883 ; be avoided) 1884 ; exit: SF = 0 if success 1885 ; SF = 1 if failure (CX was non-zero on call) 1886 0 0000B58C 8026[0000]FE and byte [rwmode],~ 1 ;mark it as a read 0 0000B591 B004 mov al,CMD_INPUT 1889 rdwr_block: 0 0000B593 51 push cx 0 0000B594 E896FC call blockif ;current drive, track,.... 0 0000B597 59 pop cx 0 0000B598 7902 jns rdwrb5 0 0000B59A E301 jcxz rdwrb10 ; test if any disk error detected 1895 rdwrb5: 0 0000B59C C3 ret ; skip if yes 1897 rdwrb10: 0 0000B59D A2[0000] mov [ioexerr],al ; save extended error 0 0000B5A0 84C0 test al,al ; is it write protect error ? 0 0000B5A2 7503 jnz rdwrb20 ; we have dirty buffers we can't write 0 0000B5A4 E8[0000] call discard_dirty ; out, so throw 'em away 1902 rdwrb20: 0 0000B5A7 A0[3500] mov al,[adrive] ; if error on different drive 0 0000B5AA 3A06[0300] cmp al,[physical_drv] ; treat error as media change 0 0000B5AE 7409 je generate_critical_error ; if same drive, report error 0 0000B5B0 E8[0000] call discard_all ; discard all buffers on drive 0 0000B5B3 E8[0000] call discard_files ; and flush files 0 0000B5B6 E9[0000] jmp fdos_restart ; try to restart the instruction 1909 1910 generate_critical_error: 1911 ;----------------------- 1912 ; On Entry: 1913 ; err_drv, rwmode, ioexerr set up 1914 ; On Exit: 1915 ; None - we don't come back 1916 ; 0 0000B5B9 A0[0000] mov al,[ioexerr] ; AL = BIOS error return byte 0 0000B5BC 98 cbw ; make it a word 0 0000B5BD 83F80F cmp ax,15 ; only handle sensible errors 0 0000B5C0 7203 jb gen_crit_err10 ; anything else becomes 0 0000B5C2 B80C00 mov ax,12 ; general failure 1922 gen_crit_err10: 0 0000B5C5 F7D8 neg ax ; convert to our negative errors 0 0000B5C7 83C0ED add ax,ED_PROTECT ; and start with write protect 0 0000B5CA E9[0000] jmp fdos_error ; now return with error 1926 1927 1928 clus2sec: ; convert from cluster/offset to sector/offset 1929 ;-------- 1930 ; On Entry: 1931 ; DX:AX = cluster 1932 ; CX:BX = byte offset in cluster 1933 ; On Exit: 1934 ; DX:AX = sector 1935 ; BX = byte offset in sector 1936 ; 1937 ; xchg ax,cx ; remember cluster in CX 0 0000B5CD 83E802 sub ax,2 ; minus 2 reserved clusters 0 0000B5D0 83DA00 sbb dx,0 0 0000B5D3 52 push dx ; save cluster on stack 0 0000B5D4 50 push ax 1942 ; xor dx,dx 0 0000B5D5 87D1 xchg dx,cx 0 0000B5D7 93 xchg ax,bx ; DX:AX = byte offset 0 0000B5D8 F736[0400] div word [psecsiz] ; AX = sector offset, DX = byte offset 0 0000B5DC 89D3 mov bx,dx ; BX = byte offset in sector 1947 ; xchg ax,cx ; AX = cluster, CX = sector offset 0 0000B5DE 89C1 mov cx,ax ; CX = sector offset 1949 ; dec ax 1950 ; dec ax ; forget about 2 reserved clusters 1951 ; mul secperclu ; DX:AX = offset of cluster 0 0000B5E0 31C0 xor ax,ax ; sectors per cluster 0 0000B5E2 50 push ax 0 0000B5E3 FF36[2F00] push word [secperclu] 0 0000B5E7 83EC08 sub sp,8 ; reserve space for product 0 0000B5EA E81F01 call mul32 ; multiply cluster with sectors per cluster 0 0000B5ED 58 pop ax ; DX:AX = sector number 0 0000B5EE 5A pop dx 0 0000B5EF 83C40C add sp,12 ; clean up stack 1960 ; add ax,datadd 1961 ; adc dx,0 ; DX:AX = offset of start of dir 0 0000B5F2 0306[1500] add ax,[bdatadd] 0 0000B5F6 1316[1700] adc dx,[bdatadd+2] ; DX:AX = offset of start of dir 0 0000B5FA 01C8 add ax,cx ; DX:AX - add in sector offset 0 0000B5FC 83D200 adc dx,0 0 0000B5FF C3 ret 1967 1968 div64: ; 64-bit division 1969 ;-------- 1970 ; On Entry: 1971 ; 64-bit dividend & 32-bit divisor on stack 1972 ; space for 32-bit quotient & remainder reserved on stack 1973 ; SP-20 1974 ; On Exit: 1975 ; 32-bit quotient & remainder on stack 1976 ; SP-20 1977 ; Modified registers: 1978 ; AX,CX,DX,BP,SI 0 0000B600 89E5 mov bp,sp ; base address of temporary variables 0 0000B602 31C0 xor ax,ax ; clear work registers 0 0000B604 31D2 xor dx,dx 0 0000B606 31F6 xor si,si 0 0000B608 B94000 mov cx,64 ; 64 bits 1984 div64_loop: 0 0000B60B D16606 shl word ptr [2+4 + bp],1 ; multiply quotient with two 0 0000B60E D15608 rcl word ptr [2+6 + bp],1 0 0000B611 D1660E shl word ptr [2+12 + bp],1 ; shift one bit from dividend 0 0000B614 D15610 rcl word ptr [2+14 + bp],1 0 0000B617 D15612 rcl word ptr [2+16 + bp],1 0 0000B61A D15614 rcl word ptr [2+18 + bp],1 0 0000B61D D1D0 rcl ax,1 ; to work registers 0 0000B61F D1D2 rcl dx,1 0 0000B621 D1D6 rcl si,1 0 0000B623 83FE00 cmp si,0 ; larger than divisor? 0 0000B626 750C jne div64_1 0 0000B628 3B560C cmp dx,[2+10 + bp] ; compare second word with divisor 0 0000B62B 7214 jb div64_2 0 0000B62D 7705 ja div64_1 0 0000B62F 3B460A cmp ax,[2+8 + bp] ; compare first word 0 0000B632 720D jb div64_2 2001 div64_1: 0 0000B634 834E0601 or word ptr [2+4 + bp],1 ; divisor fits one time 0 0000B638 2B460A sub ax,[2+8 + bp] ; subtract divisor 0 0000B63B 1B560C sbb dx,[2+10 + bp] 0 0000B63E 83DE00 sbb si,0 2006 div64_2: 0 0000B641 E2C8 loop div64_loop ; loop back if more bits to shift 0 0000B643 894602 mov [2 + bp],ax ; save remainder onto stack 0 0000B646 895604 mov [2+2 + bp],dx 0 0000B649 C3 ret 2011 2012 div32: ; 32-bit division 2013 ;-------- 2014 ; On Entry: 2015 ; 32-bit dividend & divisor on stack 2016 ; space for 32-bit quotient & remainder reserved on stack 2017 ; SP-16 2018 ; On Exit: 2019 ; 32-bit quotient & remainder on stack 2020 ; SP-16 2021 ; Modified registers: 2022 ; AX,CX,DX,BP 0 0000B64A 89E5 mov bp,sp ; base address of temporary variables 0 0000B64C 31D2 xor dx,dx 0 0000B64E 39560C cmp [2+10 + bp],dx ; if divisor high != 0 => 32bit div 0 0000B651 751E jne div32_full 0 0000B653 8B4E0A mov cx,[2+8 + bp] ; CX <- divisor low 0 0000B656 895604 mov [2+2 + bp],dx ; clear remainder high, guaranteed to 2029 ; ...be zero here 0 0000B659 8B4610 mov ax,[2+14 + bp] ; AX <- dividend high 0 0000B65C 85C0 test ax,ax ; if both dividend and divisor are 2032 ; ...16bit, perform one 16bit division 0 0000B65E 7402 jz div16 ; ...else perform two 16bit divisions 0 0000B660 F7F1 div cx ; divide dividend high by divisor low 0 0000B662 894608 div16: mov [2+6 + bp],ax ; 6[bp] <- quotient high 0 0000B665 8B460E mov ax,[2+12 + bp] ; AX <- dividend low 0 0000B668 F7F1 div cx ; divide dividend low by divisor low 2038 ; ...DX -> remainder of previous 2039 ; ... division or zero 0 0000B66A 895602 mov [2 + bp],dx ; store remainder low 0 0000B66D 894606 mov [2+4 + bp],ax ; store quotient low 0 0000B670 C3 ret 2043 div32_full: 0 0000B671 31C0 xor ax,ax ; clear registers, DX cleared above 0 0000B673 B92000 mov cx,32 ; 32 iterations (bits) 2046 div32_loop: 0 0000B676 D16606 shl word ptr [2+4 + bp],1 ; multiply quotient with two 0 0000B679 D15608 rcl word ptr [2+6 + bp],1 0 0000B67C D1660E shl word ptr [2+12 + bp],1 ; shift one bit from dividend 0 0000B67F D15610 rcl word ptr [2+14 + bp],1 0 0000B682 D1D0 rcl ax,1 ; to work registers 0 0000B684 D1D2 rcl dx,1 0 0000B686 3B560C cmp dx,[2+10 + bp] ; compare high word with divisor 0 0000B689 7211 jb div32_2 0 0000B68B 7705 ja div32_1 0 0000B68D 3B460A cmp ax,[2+8 + bp] ; compare low word 0 0000B690 720A jb div32_2 2058 div32_1: 0 0000B692 834E0601 or word ptr [2+4 + bp],1 ; divisor fits one time 0 0000B696 2B460A sub ax,[2+8 + bp] ; subtract divisor 0 0000B699 1B560C sbb dx,[2+10 + bp] 2062 div32_2: 0 0000B69C E2D8 loop div32_loop ; loop back if more bits to shift 0 0000B69E 894602 mov [2 + bp],ax ; save remainder onto stack 0 0000B6A1 895604 mov [2+2 + bp],dx 0 0000B6A4 C3 ret 2067 2068 2069 mul64: ; 64-bit multiplication 2070 ;-------- 2071 ; On Entry: 2072 ; 64-bit factors on stack 2073 ; space for 128-bit product reserved on stack 2074 ; SP-32 2075 ; On Exit: 2076 ; 64-bit product on stack 2077 ; SP-32 2078 ; Carry flag set if result does not fit in quad word 2079 ; Modified registers: 2080 ; AX,BX,CX,DX 0 0000B6A5 06 push es ; save ES 0 0000B6A6 55 push bp ; save BP 0 0000B6A7 56 push si ; save SI 0 0000B6A8 57 push di ; save DI 0 0000B6A9 16 push ss 0 0000B6AA 07 pop es 0 0000B6AB 89E5 mov bp,sp ; base address of temporary variables 0 0000B6AD 83C50A add bp,10 0 0000B6B0 89EF mov di,bp ; clear result 0 0000B6B2 31C0 xor ax,ax 0 0000B6B4 B90400 mov cx,4 0 0000B6B7 FC cld 0 0000B6B8 F3AB rep stosw 0 0000B6BA 31F6 xor si,si ; start with lowest words of factors 2095 mul64_10: 0 0000B6BC 31FF xor di,di 2097 mul64_20: 0 0000B6BE 89F3 mov bx,si ; compute offset in result 0 0000B6C0 01FB add bx,di 0 0000B6C2 83C304 add bx,4 0 0000B6C5 B91000 mov cx,16 ; number of carry additions left 0 0000B6C8 29D9 sub cx,bx 0 0000B6CA D1E9 shr cx,1 ; / 2 = number of word additions 0 0000B6CC 8B4210 mov ax,[16 + bp+si] ; multiply two words 0 0000B6CF F76318 mul word ptr [24 + bp+di] 0 0000B6D2 87DF xchg bx,di 0 0000B6D4 0143FC add [bp+di-4],ax ; and add the product to the result 0 0000B6D7 1153FE adc [bp+di-2],dx 0 0000B6DA E309 jcxz mul64_40 ; skip if highest words 2110 mul64_30: 0 0000B6DC 7307 jnc mul64_40 ; no carry, so no further adds needed 0 0000B6DE 831300 adc word ptr [bp+di],0 ; otherwise add zero 0 0000B6E1 47 inc di 0 0000B6E2 47 inc di 0 0000B6E3 E2F7 loop mul64_30 ; until no carry left over 2116 mul64_40: 0 0000B6E5 87DF xchg bx,di 0 0000B6E7 47 inc di ; next word in first factor 0 0000B6E8 47 inc di 0 0000B6E9 83FF06 cmp di,6 ; already highest word? 0 0000B6EC 76D0 jbe mul64_20 ; next multiplication 0 0000B6EE 46 inc si ; next word in second factor 0 0000B6EF 46 inc si 0 0000B6F0 83FE06 cmp si,6 ; already highest word? 0 0000B6F3 76C7 jbe mul64_10 ; next multiplication 0 0000B6F5 B90400 mov cx,4 ; check if results fits in 64 bits 0 0000B6F8 31F6 xor si,si 2128 mul64_45: 0 0000B6FA 837A0800 cmp word ptr [8 + bp+si],0 ; zero? 0 0000B6FE 7506 jnz mul64_50 ; if not, then skip and set carry 0 0000B700 46 inc si ; next word to compare 0 0000B701 46 inc si 0 0000B702 E2F6 loop mul64_45 ; until highest dword has been checked 0 0000B704 EB01 jmp mul64_60 ; 64-bit result 2135 mul64_50: 0 0000B706 F9 stc 2137 mul64_60: 0 0000B707 5F pop di ; restore DI again 0 0000B708 5E pop si ; restore SI 0 0000B709 5D pop bp ; restore BP 0 0000B70A 07 pop es ; restore ES 0 0000B70B C3 ret 2143 2144 mul32: ; 32-bit multiplication 2145 ;-------- 2146 ; On Entry: 2147 ; 32-bit factors on stack 2148 ; space for 64-bit product reserved on stack 2149 ; SP-16 2150 ; On Exit: 2151 ; 64-bit product on stack 2152 ; SP-16 2153 ; Carry flag set if result does not fit in double word 2154 ; Modified registers: 2155 ; AX,DX 0 0000B70C 55 push bp ; save BP 0 0000B70D 89E5 mov bp,sp ; base address of temporary variables 0 0000B70F 8B460E mov ax,[4+10 + bp] ; multiply high word of factors 0 0000B712 F76612 mul word ptr [4+14 + bp] 0 0000B715 894608 mov [4+4 + bp],ax ; store result 0 0000B718 89560A mov [4+6 + bp],dx 0 0000B71B 8B460E mov ax,[4+10 + bp] ; multiply high word of first factor with low word of second 0 0000B71E F76610 mul word ptr [4+12 + bp] 0 0000B721 894606 mov [4+2 + bp],ax ; add result to previous 0 0000B724 015608 add [4+4 + bp],dx 0 0000B727 83560A00 adc word ptr [4+6 + bp],0 0 0000B72B 8B460C mov ax,[4+8 + bp] ; multiply low word of first factor with high word of second 0 0000B72E F76612 mul word ptr [4+14 + bp] 0 0000B731 014606 add [4+2 + bp],ax ; add result to previous 0 0000B734 115608 adc [4+4 + bp],dx 0 0000B737 83560A00 adc word ptr [4+6 + bp],0 0 0000B73B 8B460C mov ax,[4+8 + bp] ; multiply low word of first factor with low word of second 0 0000B73E F76610 mul word ptr [4+12 + bp] 0 0000B741 894604 mov [4 + bp],ax ; add result 0 0000B744 015606 add [4+2 + bp],dx 0 0000B747 83560800 adc word ptr [4+4 + bp],0 0 0000B74B 83560A00 adc word ptr [4+6 + bp],0 0 0000B74F 837E0800 cmp word ptr [4+4 + bp],0 ; 64-bit result? 0 0000B753 7506 jnz mul32_1 ; yes 0 0000B755 837E0A00 cmp word ptr [4+6 + bp],0 0 0000B759 7401 jz mul32_2 ; no 2182 mul32_1: 0 0000B75B F9 stc ; yes, set carry flag to indicate this 2184 mul32_2: 0 0000B75C 5D pop bp ; restore BP again 0 0000B75D C3 ret 2187 2188 public read_tsc 2189 read_tsc: 0 0000B75E 52 push dx 0 0000B75F 50 push ax 0 0000B760 0F31 db 0fh,31h ; RDTSC 0 0000B762 66 db 66h ; MOV lasttsc+4,EDX 0 0000B763 8916[8900] mov [lasttsc+4],dx 0 0000B767 66 db 66h ; MOV lasttsc,EAX 0 0000B768 A3[8500] mov [lasttsc],ax 0 0000B76B 58 pop ax 0 0000B76C 5A pop dx 0 0000B76D C3 ret 2200 2201 public diff_tsc 2202 diff_tsc: 0 0000B76E 52 push dx 0 0000B76F 51 push cx 0 0000B770 53 push bx 0 0000B771 50 push ax 0 0000B772 0F31 db 0fh,31h ; RDTSC 0 0000B774 66 db 66h ; MOV ECX,lasttsc+4 0 0000B775 8B0E[8900] mov cx,[lasttsc+4] 0 0000B779 66 db 66h ; MOV EBX,lasttsc 0 0000B77A 8B1E[8500] mov bx,[lasttsc] 0 0000B77E 66 db 66h ; SUB EAX,EBX 0 0000B77F 29D8 sub ax,bx 0 0000B781 66 db 66h ; SBB EDX,ECX 0 0000B782 19CA sbb dx,cx 0 0000B784 833E[8D00]00 cmp word [tscsel],0 0 0000B789 7431 je diff_tsc10 0 0000B78B 66 db 66h 0 0000B78C 52 push dx 0 0000B78D 66 db 66h 0 0000B78E 50 push ax 0 0000B78F 8B16[8D00] mov dx,[tscsel] 0 0000B793 E85300 call output_hex 0 0000B796 66 db 66h 0 0000B797 58 pop ax 0 0000B798 66 db 66h 0 0000B799 5A pop dx 0 0000B79A 66 db 66h 0 0000B79B 31DB xor bx,bx 0 0000B79D 8B1E[8D00] mov bx,[tscsel] 0 0000B7A1 4B dec bx 0 0000B7A2 D1E3 shl bx,1 0 0000B7A4 D1E3 shl bx,1 0 0000B7A6 D1E3 shl bx,1 0 0000B7A8 66 db 66h 0 0000B7A9 0187[8F00] add [tsc1 + bx],ax 0 0000B7AD 66 db 66h 0 0000B7AE 1197[9300] adc [tsc1+4 + bx],dx 0 0000B7B2 66 db 66h 0 0000B7B3 8B87[8F00] mov ax,[tsc1 + bx] 0 0000B7B7 66 db 66h 0 0000B7B8 8B97[9300] mov dx,[tsc1+4 + bx] 2243 diff_tsc10: 0 0000B7BC 66 db 66h ; PUSH EAX 0 0000B7BD 50 push ax 0 0000B7BE 66 db 66h ; PUSH EDX 0 0000B7BF 52 push dx 0 0000B7C0 58 pop ax 0 0000B7C1 5A pop dx 0 0000B7C2 E82400 call output_hex 0 0000B7C5 92 xchg ax,dx 0 0000B7C6 E82000 call output_hex 0 0000B7C9 58 pop ax 0 0000B7CA 5A pop dx 0 0000B7CB E81B00 call output_hex 0 0000B7CE 92 xchg ax,dx 0 0000B7CF E81700 call output_hex 0 0000B7D2 58 pop ax 0 0000B7D3 5B pop bx 0 0000B7D4 59 pop cx 0 0000B7D5 5A pop dx 0 0000B7D6 C3 ret 2263 2264 public output_msg 2265 output_msg: 2266 ;---------------- 2267 ; On Entry: 2268 ; si = offset CGROUP:message_msg 2269 ; On Exit: 2270 ; None 0 0000B7D7 50 push ax 0 0000B7D8 53 push bx 0 0000B7D9 AC lodsb ; get 1st character (never NULL) 2274 output_msg10: 0 0000B7DA B40E mov ah,0Eh 0 0000B7DC BB0700 mov bx,7 0 0000B7DF CD10 int 10h ; TTY write of character 0 0000B7E1 AC lodsb ; fetch another character 0 0000B7E2 84C0 test al,al ; end of string ? 0 0000B7E4 75F4 jnz output_msg10 0 0000B7E6 5B pop bx 0 0000B7E7 58 pop ax 0 0000B7E8 C3 ret 2284 2285 public output_hex 2286 output_hex: 2287 ;---------------- 2288 ; On Entry: 2289 ; dx = 2 byte hex value 2290 ; On Exit: 2291 ; None 2292 ; Used Regs: 2293 ; ax,bx,cx,dx,si 0 0000B7E9 50 push ax 0 0000B7EA 53 push bx 0 0000B7EB 51 push cx 0 0000B7EC 56 push si 0 0000B7ED 1E push ds 0 0000B7EE B90400 mov cx,4 0 0000B7F1 B40E mov ah,0eh 0 0000B7F3 BB0700 mov bx,7 2302 output_hex10: 0 0000B7F6 88F0 mov al,dh 0 0000B7F8 51 push cx 0 0000B7F9 B104 mov cl,4 0 0000B7FB D2E8 shr al,cl 0 0000B7FD 59 pop cx 0 0000B7FE 240F and al,0fh 0 0000B800 3C09 cmp al,09h ; greater 0-9? 0 0000B802 7F04 jg output_hex20 0 0000B804 0430 add al,30h 0 0000B806 EB02 jmp output_hex30 2313 output_hex20: 0 0000B808 0437 add al,37h 2315 output_hex30: 0 0000B80A CD10 int 10h 0 0000B80C 51 push cx 0 0000B80D B104 mov cl,4 0 0000B80F D3E2 shl dx,cl 0 0000B811 59 pop cx 0 0000B812 E2E2 loop output_hex10 0 0000B814 0E push cs 0 0000B815 1F pop ds 2324 ASSUME DS:PCMCODE 0 0000B816 8D36[600D] lea si,[output_hex40] 0 0000B81A E8BAFF call output_msg 2327 ASSUME DS:PCMDATA 0 0000B81D 1F pop ds 0 0000B81E 5E pop si 0 0000B81F 59 pop cx 0 0000B820 5B pop bx 0 0000B821 58 pop ax 0 0000B822 C3 ret 0 0000B823 2000 output_hex40 db 20h,0 ; end of string 2335 2336 BDOS_CODE ends 2337 2338 end === Trace listing source: drdos/bin/cmdline.lst 1 ; File : $CMDLINE.A86$ 2 ; 3 ; Description : 4 ; 5 ; Original Author : DIGITAL RESEARCH 6 ; 7 ; Last Edited By : $CALDERA$ 8 ; 9 ;-----------------------------------------------------------------------; 10 ; Copyright Work of Caldera, Inc. All Rights Reserved. 11 ; 12 ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, 13 ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. 14 ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES 15 ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF 16 ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO 17 ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE 18 ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE 19 ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, 20 ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, 21 ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, 22 ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF 23 ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT 24 ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND 25 ; CIVIL LIABILITY. 26 ;-----------------------------------------------------------------------; 27 ; 28 ; *** Current Edit History *** 29 ; *** End of Current Edit History *** 30 ; 31 ; $Log$ 32 ; CMDLINE.A86 1.8 93/03/25 15:06:03 33 ; tweak console block output 34 ; ENDLOG 35 ; 36 ; DOSPLUS Command Line Editor Routines 37 ; 38 39 [list -] 47 48 group PCMDATA PCMODE_DATA FDOS_DSEG 49 group PCMCODE PCM_CODE PCM_RODATA 50 51 ASSUME DS:PCMDATA 52 53 labelsize EDIT_CNTRL, word, cs:0 + bx ; Character and Esc Flag 54 labelsize EDIT_FUNC, word, cs:2 + bx ; Edit Function Address 55 EDIT_LEN equ 4 ; Edit Table Entry Size 56 === Switch to base=000000h -> "PCM_CODE" 57 section PCM_CODE public align=1 class=CODE 58 public read_line, edit_size 59 60 extrn dbcs_lead:near 61 extrn cmdline_read:near 62 extrn raw_read:near 63 extrn cooked_write:near 64 extrn get_dseg:near 65 extrn device_driver:near 66 67 ; WARNING - the following routines are to support history buffers 68 ; As these are optional we muset NEVER call these routines unless 69 ; the HISTORY_ON bit is set in @hist_flag. 70 71 extrn init_history:near 72 extrn save_history:near 73 extrn prev_cmd:near 74 extrn next_cmd:near 75 extrn match_cmd:near 76 extrn search_cmd:near 77 extrn match_word:near 78 extrn del_cur_history_buffer:near 79 extrn del_history_buffers:near 80 extrn goto_eol:near 81 extrn next_word:near 82 extrn prev_word:near 83 extrn del_bol:near 84 extrn deln_word:near 85 86 ; The following are public for HISTORY.PCM 87 public next_char, save_line 88 public space_out, bs_out, put_string 89 public goto_bol 90 public del_eol, del_line 91 public char_info 92 public prev_w20 93 public deln_w10 94 95 96 ; READ_LINE will read an editted line from the handle passed in BX 97 ; into a buffer with the following format:- 98 ; 99 ; BYTE Maximum String Length 100 ; BYTE Current String Length 101 ; BYTE(s) String Buffer 102 ; 103 ; On Entry:- 104 ; BX Input Handle 105 ; CX Output Handle 106 ; ES:DX Buffer Address 107 ; 108 ; On Exit:- 109 ; String input by user 110 ; 111 ; The following conventions apply for the READ_LINE function 112 ; 113 ; ES Buffer segment 114 ; SI Current cursor location in buffer (Index) 115 ; DX Last Character in Buffer (Index) 116 ; 117 DISABLE equ 80h ; Disable when advanced editing is off. 118 DISABLE_MASK equ 8000h 119 ESC_CODE equ 01h ; Scan code must be preceeded by escape byte. 120 NESC_CODE equ 00h ; No lead zero needed. 121 122 read_line: 0 00006037 55 push bp ; Save the Stack Frame Pointer 0 00006038 89E5 mov bp,sp ; Intialise it to the top of the 0 0000603A 83EC1C sub sp,RL_LENGTH ; READ_LINE control block and reserve 126 ; control block 0 0000603D 895EFE mov [RL_INPUT],bx ; Initialize the INPUT Handle 0 00006040 894EFC mov [RL_OUTPUT],cx ; the OUTPUT Handle 0 00006043 42 inc dx 0 00006044 42 inc dx ; Skip max and Returned Length 0 00006045 8956F8 mov [RL_BUFOFF],dx ; and save the buffer offset 0 00006048 8C46FA mov [RL_BUFSEG],es ; and segment 0 0000604B 31C0 xor ax,ax ; now we zero 0 0000604D 8946EC mov [RL_SAVPOS],ax ; both position in it 0 00006050 8946EE mov [RL_SAVMAX],ax ; and it's size 0 00006053 A0[0000] mov al,[column] 0 00006056 8946F6 mov [RL_INICOL],ax ; save initial column 0 00006059 A1[0000] mov ax,[cle_state] ; use to set initial editing state 0 0000605C 83E0C7 and ax,~ (RLF_MATCH+RLF_DIRTY+RLF_RECALLED) 0 0000605F 8946F4 mov [RL_FLAGS],ax ; save in flags 0 00006062 A90100 test ax,RLF_ENHANCED 0 00006065 7405 jz read_line10 0 00006067 E8[0000] call init_history ; setup the history buffers 0 0000606A EB04 jmp read_line20 145 read_line10: 0 0000606C 8366F4FD and word [RL_FLAGS],~ RLF_INS ; clear insert mode 147 read_line20: 0 00006070 89D7 mov di,dx ; di -> buffer 0 00006072 31DB xor bx,bx 0 00006074 260A5DFE or bl,byte ptr [es:di-2] ; Get the Maximum number of chars 0 00006078 895EF2 mov [RL_MAXLEN],bx ; and save for later 0 0000607B 7528 jnz read_line30 ; make sure some chars are requested 0 0000607D EB22 jmp ret_string10 ; if no chars just return 154 155 ret_string: 0 0000607F 58 pop ax ; Remove local return address 0 00006080 8B46F4 mov ax,[RL_FLAGS] ; get command line editor state 0 00006083 A3[0000] mov [cle_state],ax ; save state for next time 0 00006086 8B7EF8 mov di,[RL_BUFOFF] ; Get the buffer Offset 0 00006089 268855FF mov byte ptr [es:di-1],dl ; Return the number of characters 0 0000608D 52 push dx ; Save length of entry 0 0000608E 01D7 add di,dx ; Point to the end of the buffer 0 00006090 B00D mov al,CR 0 00006092 AA stosb ; Save CR 0 00006093 E86F04 call write_char ; Print a CR and return to the user 0 00006096 5A pop dx 0 00006097 F746F40100 test word [RL_FLAGS],RLF_ENHANCED ; Do not add to history if in 0 0000609C 7403 jz ret_string10 ; compatibility mode 0 0000609E E8[0000] call save_history ; Save state of history buffer 170 ret_string10: 0 000060A1 89EC mov sp,bp ; Remove READ_LINE control Block 0 000060A3 5D pop bp ; Restore BP and return to the caller 0 000060A4 C3 ret 174 175 176 read_line30: 0 000060A5 31F6 xor si,si ; Currently at start of buffer 0 000060A7 89F2 mov dx,si ; with an empty buffer. 179 0 000060A9 31DB xor bx,bx 0 000060AB 260A5DFF or bl,byte ptr [es:di-1] ; Check if the buffer contains any 0 000060AF 7408 jz read_line40 ; data which is terminated by a CR 0 000060B1 2680390D cmp byte ptr [es:bx+di],CR 0 000060B5 7502 jnz read_line40 0 000060B7 89DA mov dx,bx 186 read_line40: 0 000060B9 E83B03 call save_line ; Update Save Buffer variables 0 000060BC 89F2 mov dx,si 189 ; 190 ; This is out main command loop - we get a character and try to match it 191 ; with a command in our edit_table. If History is on we look at commands 192 ; with the DISABLED bit set ie. enhanced commands. 193 ; It a match isn't found we insert the character in the buffer, and optionally 194 ; try to match with previous lines in the history buffer. 195 ; 196 read_line_loop: 0 000060BE 8366F4BF and word [RL_FLAGS],~ RLF_KANJI ; initial flags 0 000060C2 E85A04 call get_char ; read the first character (AH Esc Flg) 199 0 000060C5 2E8B0E[0100] mov cx,[cs:edit_size] ; now scan the control table looking 0 000060CA BB[0300] mov bx,offset edit_table ; for a match 202 read_ll_next_cmd: 0 000060CD 25FF7F and ax,~ DISABLE_MASK ; assume normal function 0 000060D0 F746F40100 test word [RL_FLAGS],RLF_ENHANCED ; compatibilty required? then it 0 000060D5 740A jz read_ll10 ; has to be a normal function 0 000060D7 2EF7070080 test word [EDIT_CNTRL],DISABLE_MASK ; history enabled, so we make 0 000060DC 7403 jz read_ll10 ; our code match DISABLE mask 0 000060DE 0D0080 or ax,DISABLE_MASK ; of table entry 209 read_ll10: 0 000060E1 2E3B07 cmp ax,[EDIT_CNTRL] ; check for a match (Escape Flag 0 000060E4 742F je read_ll_found_cmd ; and the character) 0 000060E6 83C304 add bx,EDIT_LEN ; Add the entry length 0 000060E9 E2E2 loop read_ll_next_cmd ; and scan the whole table 214 215 ; We have failed to find a command so insert char in buffer 216 0 000060EB F6C401 test ah,ESC_CODE ; Ignore non-matched escaped keys 0 000060EE 75CE jnz read_line_loop 219 0 000060F0 E82B00 call save_char ; not an command so save the character 0 000060F3 834EF420 or word [RL_FLAGS],RLF_DIRTY ; and remember we have something new 222 223 ; Are we in search mode ? 224 0 000060F7 F746F40100 test word [RL_FLAGS],RLF_ENHANCED ; Compatibilty required? 0 000060FC 74C0 jz read_line_loop 0 000060FE F746F40C00 test word [RL_FLAGS],RLF_SEARCH+RLF_MATCH 0 00006103 74B9 jz read_line_loop ; is searching/matching on ? 0 00006105 56 push si ; save current offset 0 00006106 E8[0000] call search_cmd 0 00006109 58 pop ax ; this is our target offset 232 read_ll20: 0 0000610A 39F0 cmp ax,si ; are we there yet ? 0 0000610C 73B0 jae read_line_loop 0 0000610E 50 push ax ; no, keep rewinding cursor 0 0000610F E83401 call prev_char ; until we reach position 0 00006112 58 pop ax ; before we tried to match 0 00006113 EBF5 jmp read_ll20 239 240 read_ll_found_cmd: ; get the address of the corresponding 0 00006115 2E8B4F02 mov cx,[EDIT_FUNC] ; function from the table 0 00006119 FFD1 call cx ; execute the correct function 0 0000611B EBA1 jmp read_line_loop ; and go back for next character 244 245 ; 246 ; the SAVE_CHAR routine will write the character in AL into 247 ; the buffer in memory and then update the screen image. The 248 ; RLF_INS flag is used to determine if INSERT is active. 249 ; 250 save_c10: 0 0000611D C3 ret 252 253 save_char: 0 0000611E 80FCFF cmp ah,TRUE & 0FFh ; Ignore any un-matched escape 0 00006121 74FA jz save_c10 ; sequences 0 00006123 E8B900 call save_kanji ; Test if AL is a Kanji Character 257 ; and setup up the parameter blocks 258 ; for the INTSAVE_CHAR routine 259 ; 260 ; INTSAVE_CHAR is the internal entry point to the Character Save 261 ; routine. It assumes the following:- 262 ; 263 ; On Entry:- AX(AL) Contains the character 264 ; CX the new character length in bytes 265 ; RLF_KANJI Flag is set for a Kanji Character 266 ; RL_KANJI Contains the kanji charater 267 ; 268 intsave_char: 0 00006126 89CB mov bx,cx 0 00006128 F746F40200 test word [RL_FLAGS],RLF_INS ; Overwrite the character in the 0 0000612D 755F jnz save_c50 ; buffer currently 0 0000612F 01F3 add bx,si ; Add the current index to the character 0 00006131 3B5EF2 cmp bx,[RL_MAXLEN] ; size and compare against the buffer len 0 00006134 7353 jae bell_char ; Full ? Yes Ring dat Bell ! 275 0 00006136 39F2 cmp dx,si ; Are we at the end of the line 0 00006138 7509 jnz intsave_c10 ; No so check character types 0 0000613A 50 push ax 0 0000613B 51 push cx 0 0000613C E8C601 call skip_one_char ; Skip the coresponding character in 0 0000613F 59 pop cx 0 00006140 58 pop ax ; the save buffer 0 00006141 EB19 jmp simple_save 284 285 intsave_c10: 0 00006143 50 push ax ; Save the Input Character 0 00006144 E8F102 call char_type ; Get the character type 0 00006147 89C3 mov bx,ax ; and save in BX 0 00006149 268A05 mov al,[es:di] ; get the byte to be replaced 0 0000614C E8E902 call char_type ; and get its type 0 0000614F 80E48E and ah,CHAR_SIZE ; Mask the Character SIZE attributes 0 00006152 80E78E and bh,CHAR_SIZE ; and check both storage and display 293 ; sizes are the same for old and new 0 00006155 38FC cmp ah,bh ; and do simple save if the character 0 00006157 58 pop ax ; Restore the input character to AX(AL) 0 00006158 7518 jnz save_c30 ; type match 0 0000615A 29CA sub dx,cx ; Character overwritten so prevent 298 ; Max Index being incremented 299 300 simple_save: 0 0000615C 01CE add si,cx ; Assume at the EOL 0 0000615E 01CA add dx,cx 0 00006160 AA stosb ; Save the character typed 0 00006161 F746F44000 test word [RL_FLAGS],RLF_KANJI ; is this a Kanji character 0 00006166 7407 jz simple_s10 ; No so just output 1 character 0 00006168 E88103 call put_char ; and echo it to the user 0 0000616B 8A46F1 mov al,byte ptr [RL_KANJI+1] ; Get the high byte of the Kanji 0 0000616E AA stosb ; character save and then display it. 309 simple_s10: 0 0000616F E97A03 jmp put_char 311 ; ret 312 313 ; 314 ; The SAVE_C30 function supports the Complex overwrite conditions 315 ; where the size of the character in memory or on the display do not 316 ; match with those of the present incumbent. eg a SPACE character 317 ; overwriting a TAB or a KANJI character overwriting a SPACE. 318 ; 319 ; To minimize the complexity of the code the character to be 320 ; overwritten is deleted and the new character then inserted. 321 ; This is not an optimal solution but drastically reduces the 322 ; amount of code required. 323 ; 324 save_c30: 0 00006172 50 push ax 0 00006173 51 push cx 0 00006174 E81B01 call deln_char 0 00006177 59 pop cx 0 00006178 58 pop ax 0 00006179 39F2 cmp dx,si 0 0000617B 74DF jz simple_save 0 0000617D 834EF402 or word [RL_FLAGS],RLF_INS 0 00006181 E80A00 call save_c50 0 00006184 8366F4FD and word [RL_FLAGS],~ RLF_INS 0 00006188 C3 ret 336 337 bell_char: 0 00006189 B007 mov al,BELL 0 0000618B E97703 jmp write_char 340 ; 341 ; This code is called when INSERT mode is active and a 342 ; character (possibly Kanji) is to be inserted in the buffer 343 ; 344 ; On Entry:- CX the new character length in bytes 345 ; 346 save_c50: 0 0000618E 89CB mov bx,cx ; Save new character length 0 00006190 01D1 add cx,dx ; Add the current max to the character 0 00006192 3B4EF2 cmp cx,[RL_MAXLEN] ; size and compare against the buffer len 0 00006195 73F2 jae bell_char ; Full ? Yes Ring dat Bell ! 0 00006197 89D9 mov cx,bx ; Restore Character Length 0 00006199 39F2 cmp dx,si ; If we are at the end of the line 0 0000619B 74BF je simple_save ; Use the simple save code 354 ; 355 ; Create space in the current buffer for the new character 356 ; 0 0000619D 1E push ds 0 0000619E 56 push si 0 0000619F 57 push di 0 000061A0 89D1 mov cx,dx 0 000061A2 29F1 sub cx,si ; CX -> Number of bytes to move 0 000061A4 89D7 mov di,dx 0 000061A6 037EF8 add di,[RL_BUFOFF] ; DI -> End of Destination Offset 0 000061A9 01DF add di,bx 0 000061AB 4F dec di ; -> + Insert Char len - 1 0 000061AC 89FE mov si,di 0 000061AE 29DE sub si,bx ; SI -> DI - Insert Char Len 0 000061B0 06 push es 0 000061B1 1F pop ds ; DS == ES 0 000061B2 FD std ; Make the right amount of space in 0 000061B3 F3A4 rep movsb ; the buffer 0 000061B5 FC cld 0 000061B6 5F pop di 0 000061B7 5E pop si 0 000061B8 1F pop ds 376 0 000061B9 01DA add dx,bx ; Update the Buffer Length 0 000061BB AA stosb ; Save the New character 0 000061BC F746F44000 test word [RL_FLAGS],RLF_KANJI ; Check if this was a Kanji Character 0 000061C1 7403 jz save_c60 ; No 0 000061C3 86C4 xchg al,ah 0 000061C5 AA stosb ; Yes Save high byte 383 384 save_c60: 0 000061C6 89D1 mov cx,dx 0 000061C8 29F1 sub cx,si ; Display the updated string 0 000061CA 01DE add si,bx 0 000061CC 56 push si ; Save the Updated Index 0 000061CD 89FE mov si,di 0 000061CF 29DE sub si,bx ; Get the offset of the new char 0 000061D1 E80803 call put_string ; in the buffer and display all 0 000061D4 5E pop si ; Restore the new index 0 000061D5 87FA xchg di,dx ; and calculate the number of BS 0 000061D7 E8CD02 call calc_chars ; characters required to get back 0 000061DA 87FA xchg di,dx 0 000061DC E9F102 jmp bs_out 397 ; 398 ; On Entry: AL First byte of Character 399 ; 400 ; On Exit: AX Complete Character Code 401 ; CX Character Size Bytes 402 ; RL_KANJI and RLF_KANJI set correctly 403 ; 404 save_kanji: 0 000061DF 8366F4BF and word [RL_FLAGS],~ RLF_KANJI 0 000061E3 8946F0 mov [RL_KANJI],ax ; Save the Character 0 000061E6 E84F02 call char_type ; Is this the first byte of a 0 000061E9 F6C408 test ah,CHAR_KANJI ; two byte Kanji character 0 000061EC B90100 mov cx,1 ; Character size in bytes 0 000061EF 7410 jz save_k10 ; No 0 000061F1 834EF440 or word [RL_FLAGS],RLF_KANJI ; Set internal Flag 0 000061F5 E82703 call get_char ; Get the high byte and save 0 000061F8 8846F1 mov byte ptr [RL_KANJI+1],al ; in the local variable 0 000061FB 8B46F0 mov ax,[RL_KANJI] ; Get the complete character 0 000061FE B90200 mov cx,2 ; Character size in bytes 416 save_k10: 0 00006201 C3 ret 418 419 ; 420 ; The following group of functions modify the flags which control 421 ; the command line editor. 422 ; 423 toggle_ins: 0 00006202 8376F402 xor word [RL_FLAGS],RLF_INS ; Toggle the OverWrite/Insert 0 00006206 C3 ret ; Flag 426 427 toggle_search: 0 00006207 8366F4F7 and word [RL_FLAGS],~ RLF_MATCH ; clear match bit 0 0000620B 8376F404 xor word [RL_FLAGS],RLF_SEARCH ; Toggle the Search on/off flag 0 0000620F C3 ret 431 432 ; 433 ; This group of functions moves the cursor along the display 434 ; as well as updating the local variables. 435 ; 436 goto_bol: 0 00006210 85F6 test si,si ; Move the cursor to the begining of 0 00006212 740F jz goto_b10 ; the displayed line 0 00006214 89F7 mov di,si ; Set the buffer index to the 0 00006216 31F6 xor si,si ; start of the line and the current 0 00006218 E88C02 call calc_chars ; location 0 0000621B E8B202 call bs_out 0 0000621E 31F6 xor si,si 0 00006220 8B7EF8 mov di,[RL_BUFOFF] 445 goto_b10: 0 00006223 C3 ret 447 448 next_char: 0 00006224 39D6 cmp si,dx 0 00006226 7503 jnz next_c05 ; Treat this as "F1" when we at the 0 00006228 E92501 jmp copy_char ; end of the line 452 453 next_c05: 0 0000622B 268A05 mov al,[es:di] ; Get the Offset of the next character 0 0000622E B90100 mov cx,1 ; the character itself and assume 0 00006231 E80402 call char_type ; it is 1 byte long 0 00006234 F6C408 test ah,CHAR_KANJI 0 00006237 7401 jz next_c10 0 00006239 41 inc cx 460 next_c10: 0 0000623A 87F7 xchg si,di ; Get the string offset in SI 0 0000623C E89D02 call put_string ; display the character and 0 0000623F 87F7 xchg si,di ; restore the register contents 0 00006241 01CE add si,cx 0 00006243 01CF add di,cx 0 00006245 C3 ret 467 468 prev_char: 0 00006246 85F6 test si,si ; begining of line ? 0 00006248 742B jz prev_w30 0 0000624A 52 push dx 0 0000624B 56 push si 0 0000624C 57 push di 0 0000624D 8B76F8 mov si,[RL_BUFOFF] ; Scan from the begining of the buffer 0 00006250 89F2 mov dx,si ; keeping the last match in DX 476 prev_c10: 0 00006252 E82702 call char_info ; Get the character information 0 00006255 39FE cmp si,di ; Stop when we get to the current 0 00006257 7404 je prev_w20 ; character location 0 00006259 89F2 mov dx,si ; Save current location 0 0000625B EBF5 jmp prev_c10 ; and repeat 482 483 prev_w20: 0 0000625D 29D6 sub si,dx ; Calculate character length 0 0000625F 56 push si ; save for update 486 0 00006260 2B7EF8 sub di,[RL_BUFOFF] ; Convert Offset to Index 0 00006263 F7DE neg si 0 00006265 01FE add si,di ; Set the buffer index to the current 0 00006267 E83D02 call calc_chars ; location and the previous character 0 0000626A E86302 call bs_out ; BackSpace over character 0 0000626D 59 pop cx ; Restore the character size 0 0000626E 5F pop di 0 0000626F 5E pop si 0 00006270 5A pop dx 0 00006271 29CE sub si,cx ; Update the Index and Pointer 0 00006273 29CF sub di,cx ; variables. 498 prev_w30: 0 00006275 C3 ret 500 501 ; 502 ; This group of functions deletes characters or groups of characters 503 ; from the buffer. 504 ; 505 506 delf_char: 0 00006276 39D6 cmp si,dx ; any chars to our right ? 0 00006278 7218 jb deln_char ; yes, delete them first 0 0000627A E98800 jmp skip_one_char 510 ; ret ; discard next saved char 511 512 del_eol: 0 0000627D 89D1 mov cx,dx 0 0000627F 29F1 sub cx,si ; Calculate the number of bytes to 0 00006281 E304 jcxz del_eol10 ; delete and jump to DELN_WORD if 0 00006283 01F9 add cx,di ; non zero. Convert to an offset 0 00006285 EB1E jmp deln_w10 ; and jmp to common code. 518 del_eol10: 0 00006287 C3 ret 520 521 delp_char: 0 00006288 09F6 or si,si 0 0000628A 74FB jz del_eol10 ; Ignore if the user is at the start 0 0000628C E89900 call back_one_char ; of the line otherwise move back one 0 0000628F E8B4FF call prev_char ; character in the line buffer 526 527 528 deln_char: 0 00006292 39F2 cmp dx,si 0 00006294 74F1 jz del_eol10 0 00006296 268A05 mov al,[es:di] ; Get the Offset of the next character 0 00006299 8D4D01 lea cx,[1 + di] ; the character itself and assume 0 0000629C E89901 call char_type ; it is 1 byte long 0 0000629F F6C408 test ah,CHAR_KANJI 0 000062A2 7401 jz deln_w10 0 000062A4 41 inc cx 537 ; jmp deln_w10 538 539 ; 540 ; The 3 delete functions come together at this point with the standard 541 ; register format Plus CX is the offset of the first character not to 542 ; be deleted. 543 ; 544 deln_w10: 0 000062A5 51 push cx ; Save Delete Offset 0 000062A6 87FA xchg di,dx ; Determine the no of characters 0 000062A8 E8FC01 call calc_chars ; displayed to the end of the line 0 000062AB 87FA xchg di,dx 0 000062AD 89CB mov bx,cx ; Save the Column count 0 000062AF 58 pop ax ; restore the delete offset 551 0 000062B0 53 push bx 0 000062B1 53 push bx ; Save the count twice 554 0 000062B2 56 push si 0 000062B3 57 push di 0 000062B4 89D1 mov cx,dx 0 000062B6 29F1 sub cx,si ; No of chars from old EOL 0 000062B8 89C6 mov si,ax ; Get the Source Offset 0 000062BA 29F8 sub ax,di ; calculate its length. 0 000062BC 29C2 sub dx,ax ; Update the string length 562 0 000062BE 29C1 sub cx,ax ; Number of chars to copy 0 000062C0 1E push ds ; Move the contents of the 0 000062C1 06 push es 0 000062C2 1F pop ds ; string down in memory and 0 000062C3 F3A4 rep movsb ; then update the screen image 0 000062C5 1F pop ds 0 000062C6 5E pop si 0 000062C7 5F pop di ; Get the current buffer offset 571 ; Restore SWAPPED SI <-> DI 572 0 000062C8 89D1 mov cx,dx ; Calculate the length of the 0 000062CA 29F9 sub cx,di ; string and print it alll 0 000062CC E80D02 call put_string 0 000062CF 87F7 xchg si,di ; Restore SI and DI 577 0 000062D1 E307 jcxz deln_w20 0 000062D3 87FA xchg di,dx ; Calculate the number of columns 0 000062D5 E8CF01 call calc_chars ; displayed 0 000062D8 87FA xchg di,dx 582 583 deln_w20: 0 000062DA 5B pop bx ; Restore the original line length 0 000062DB 29CB sub bx,cx ; and calculate the number of spaces 0 000062DD 89D9 mov cx,bx ; required to overwrite the data 0 000062DF E8EA01 call space_out 588 0 000062E2 59 pop cx ; Finally move the cursor back to 0 000062E3 E9EA01 jmp bs_out ; its correct place 591 592 593 594 595 ; 596 ; Delete the contents of the complete line 597 ; 598 del_line: 0 000062E6 C746EC0000 mov word [RL_SAVPOS],0 ; Reset the buffer index 0 000062EB 85D2 test dx,dx 0 000062ED 7415 jz del_l10 0 000062EF E81EFF call goto_bol ; Jump to the begining of the line 0 000062F2 89D7 mov di,dx ; calculate the number of display 0 000062F4 E8B001 call calc_chars ; columns it currently takes up 0 000062F7 E8D201 call space_out ; Overwrite with spaces 0 000062FA E8D301 call bs_out ; Move back to the start of the line 0 000062FD 31F6 xor si,si ; and update all the initial variables 0 000062FF 89F2 mov dx,si 0 00006301 8B7EF8 mov di,[RL_BUFOFF] 610 del_l10: 0 00006304 C3 ret 612 613 ; 614 ; The following routines manipulate the SAVE Buffer data. Which 615 ; is initialised on entry to this function. 616 ; 617 ; SKIP_ONE_CHAR increments the Save Buffer control variables and 618 ; returns the number of bytes skipped in CX. 619 ; 620 ; On Entry: Standard Registers 621 ; 622 ; On Exit: AX Next Character in Buffer 623 ; CX Character Size (Bytes) 624 ; 625 skip_one_char: 0 00006305 31C9 xor cx,cx 0 00006307 8B5EEC mov bx,[RL_SAVPOS] ; Update the Save Buffer variables 0 0000630A 3B5EEE cmp bx,[RL_SAVMAX] ; Check the current save buffer is 0 0000630D 7315 jae soc_20 ; valid and has not been exhausted. 630 ; Otherwise increment the RL_SAVPOS 0 0000630F BB[0000] mov bx,offset savbuf ; pointer by one character. This 0 00006312 035EEC add bx,[RL_SAVPOS] ; means that the RL_SAVPOS can be 0 00006315 8A07 mov al,[bx] ; incremented by 1 or 2 depending on 0 00006317 E81E01 call char_type ; the contents of the buffer 0 0000631A F6C408 test ah,CHAR_KANJI 0 0000631D 7404 jz soc_10 0 0000631F 8A6701 mov ah,[1 + bx] 0 00006322 41 inc cx 639 soc_10: 0 00006323 41 inc cx 641 soc_20: 0 00006324 014EEC add [RL_SAVPOS],cx 0 00006327 C3 ret 644 ; 645 ; 646 ; BACK_ONE_CHAR decrements the Save Buffer control variables and 647 ; returns the number of bytes skipped in CX. 648 ; 649 ; On Entry: Standard Registers 650 ; 651 ; On Exit: RL_SAVPOS points to previous buffer char 652 ; AX,BX,CX,DX Unknown 653 ; 654 back_one_char: 0 00006328 52 push dx 0 00006329 BB[0000] mov bx,offset savbuf ; Get the Buffer address 0 0000632C 89D9 mov cx,bx 0 0000632E 034EEC add cx,[RL_SAVPOS] ; CX is the Current location 0 00006331 89DA mov dx,bx ; DX is last matching character 660 boc_10: 0 00006333 39CB cmp bx,cx ; Have we reached the current Char 0 00006335 7410 jz boc_20 ; Yes exit and update buffer 0 00006337 89DA mov dx,bx ; Update last character location 0 00006339 8A07 mov al,[bx] ; incremented by 1 or 2 depending on 0 0000633B E8FA00 call char_type ; the contents of the buffer 0 0000633E 43 inc bx 0 0000633F F6C408 test ah,CHAR_KANJI ; Increment pointer by 2 for a Kanji 0 00006342 74EF jz boc_10 ; character 0 00006344 43 inc bx 0 00006345 EBEC jmp boc_10 671 672 boc_20: 0 00006347 81EA[0000] sub dx,offset savbuf ; Calculate the character Index 0 0000634B 8956EC mov [RL_SAVPOS],dx ; and save in RL_SAVPOS 0 0000634E 5A pop dx 0 0000634F C3 ret 677 678 copy_char: 0 00006350 39F2 cmp dx,si ; If at end of line copy characters 0 00006352 7405 jz copy_c5 0 00006354 E8CDFE call next_char ; Otherwise just move by 1 0 00006357 EB0A jmp copy_c10 683 684 copy_c5: 0 00006359 E8A9FF call skip_one_char ; Calculate Bytes to copy 0 0000635C E305 jcxz copy_c10 ; Skip Update in no characters skipped 0 0000635E 294EEC sub [RL_SAVPOS],cx ; Restore the Buffer Position 0 00006361 EB23 jmp copy_a10 ; and copy the data 689 copy_c10: 0 00006363 C3 ret 691 692 copy_till_char: 0 00006364 39F2 cmp dx,si ; Copy out if at end of line 0 00006366 7508 jnz move_till_char 0 00006368 E84800 call skip_till_char ; Returns index to the next char 0 0000636B 294EEC sub [RL_SAVPOS],cx 0 0000636E EB16 jmp copy_a10 698 move_till_char: 0 00006370 8976EC mov [RL_SAVPOS],si ; Start search from the current 0 00006373 E83D00 call skip_till_char ; position 0 00006376 E307 jcxz no_move ; CX=0 - dont move 702 move_along: 0 00006378 51 push cx 0 00006379 E8A8FE call next_char ; Shuttle along the line until 0 0000637C 59 pop cx ; we reach the character 0 0000637D E2F9 loop move_along 707 no_move: 0 0000637F C3 ret 709 710 copy_all: 0 00006380 8B4EEE mov cx,[RL_SAVMAX] ; Calculate the number of bytes to 0 00006383 2B4EEC sub cx,[RL_SAVPOS] ; copy from the buffer. 713 copy_a10: 0 00006386 83F900 cmp cx,0 ; do we have nothing to copy 0 00006389 7E27 jle copy_a30 ; (or less than nothing..) 716 0 0000638B FF76F4 push word [RL_FLAGS] ; Save State flags and prevent 0 0000638E 834EF402 or word [RL_FLAGS],RLF_INS ; SAVPOS being modified 719 copy_a20: 0 00006392 51 push cx 0 00006393 8366F4BF and word [RL_FLAGS],~ RLF_KANJI 0 00006397 E86BFF call skip_one_char ; Return the next character and its 0 0000639A 83F901 cmp cx,1 0 0000639D 740A jz copy_a25 ; size in bytes 0 0000639F 8946F0 mov [RL_KANJI],ax ; Save the Kanji Character and 0 000063A2 834EF440 or word [RL_FLAGS],RLF_KANJI ; set the control flag 0 000063A6 5B pop bx 0 000063A7 4B dec bx 0 000063A8 53 push bx ; Decrement the Loop Count 730 731 copy_a25: 0 000063A9 E87AFD call intsave_char ; Save the character 0 000063AC 59 pop cx ; and repeat till all bytes have 0 000063AD E2E3 loop copy_a20 ; been copied 0 000063AF 8F46F4 pop word [RL_FLAGS] ; Restore State Flags 736 copy_a30: 0 000063B2 C3 ret 738 739 skip_till_char: 0 000063B3 E86901 call get_char ; Get the first character 0 000063B6 E826FE call save_kanji ; Setup RL_KANJI etc. 0 000063B9 52 push dx 0 000063BA E848FF call skip_one_char ; don't match on 1st char 0 000063BD 89CA mov dx,cx ; remember we've skipped 1st char 0 000063BF E32F jcxz stc_40 ; buffer exhausted 746 stc_10: 0 000063C1 E841FF call skip_one_char ; Get the Next Character 0 000063C4 E32A jcxz stc_40 ; Buffer exhausted 0 000063C6 01CA add dx,cx ; Update the Total Byte Count 0 000063C8 83F902 cmp cx,2 0 000063CB 740E jz stc_20 ; Was this a Kanji Character 0 000063CD F746F44000 test word [RL_FLAGS],RLF_KANJI ; No but are we looking for one ? 0 000063D2 75ED jnz stc_10 ; Yes so get the next character 0 000063D4 3A46F0 cmp al,byte ptr [RL_KANJI] ; Have we got a matching character ? 0 000063D7 75E8 jnz stc_10 ; No so look again 0 000063D9 EB0C jmp stc_30 ; Return Sucess 757 758 stc_20: ; Kanji Character in Buffer 0 000063DB F746F44000 test word [RL_FLAGS],RLF_KANJI ; Are we looking for a Kanji Char 0 000063E0 74DF jz stc_10 ; No so try again 0 000063E2 3B46F0 cmp ax,[RL_KANJI] ; Check the character and repeat 0 000063E5 75DA jnz stc_10 ; if they donot match 763 764 stc_30: ; Character Match 0 000063E7 29CA sub dx,cx ; Correct the Total Byte Count 0 000063E9 294EEC sub [RL_SAVPOS],cx ; point to the matching char 0 000063EC 87CA xchg cx,dx ; and return the Match Count 0 000063EE 5A pop dx 0 000063EF C3 ret 770 771 stc_40: ; No Match 0 000063F0 2956EC sub [RL_SAVPOS],dx ; Restore RL_SAVPOS to orginal value 0 000063F3 31C9 xor cx,cx ; and return 0000 characters skipped 0 000063F5 5A pop dx 0 000063F6 C3 ret 776 777 ; 778 ; Update the Save buffer with the contents of the users 779 ; line buffer. 780 ; 781 ; On Entry: ES:DI -> Current location in Buffer 782 ; DX No. of bytes in buffer 783 ; 784 ; On Exit: Update RL_SAVMAX, RL_SAVPOS, RL_SAVBUF 785 ; 786 save_line: 0 000063F7 31C0 xor ax,ax 0 000063F9 8946EC mov [RL_SAVPOS],ax 0 000063FC 8946EE mov [RL_SAVMAX],ax 0 000063FF 89D1 mov cx,dx ; Current Line Length 0 00006401 E31E jcxz save_l10 0 00006403 81F98000 cmp cx,savbuf_size ; clip the amount saved 0 00006407 7203 jb save_l5 ; to be a maximum of 0 00006409 B98000 mov cx,savbuf_size ; the save buffer size 795 save_l5: 0 0000640C 894EEE mov [RL_SAVMAX],cx ; Set the Save Data Length 0 0000640F 1E push ds 0 00006410 06 push es 0 00006411 56 push si 0 00006412 57 push di 801 0 00006413 1E push ds 0 00006414 07 pop es 0 00006415 C576F8 lds si,[RL_BUFPTR] 0 00006418 BF[0000] mov di,offset savbuf 0 0000641B F3A4 rep movsb ; save the data 0 0000641D 5F pop di 0 0000641E 5E pop si 0 0000641F 07 pop es 0 00006420 1F pop ds 811 save_l10: 812 ; ret 813 814 ignore_char: 0 00006421 C3 ret 816 817 mem_line: ;; JFL save from beginning of line 0 00006422 E8D2FF call save_line 0 00006425 E9E8FD jmp goto_bol 820 ; ret 821 822 823 eof_char: ;; JFL make F6 return a CTL Z 0 00006428 B01A mov al,01Ah 0 0000642A B90100 mov cx,1 0 0000642D E9F6FC jmp intsave_char 827 ; ret 828 829 ctlat_char: ;; JFL make F7 return a CTL @ 0 00006430 B000 mov al,0h 0 00006432 B90100 mov cx,1 0 00006435 E9EEFC jmp intsave_char 833 ; ret 834 835 836 ; 837 ; CHAR_TYPE get the next character from the buffer ES:SI and returns 838 ; its type in AH using the equates CHAR_????. The character is returned 839 ; in AL. 840 ; 841 ; 842 ; 843 char_type: 0 00006438 B481 mov ah,CHAR_SPACE | CHAR_STD ; WhiteSpace 0 0000643A 3C20 cmp al,' ' 0 0000643C 743D jz char_t100 0 0000643E B402 mov ah,CHAR_TAB ; Tab Character 0 00006440 3C09 cmp al,TAB 0 00006442 7437 jz char_t100 0 00006444 B490 mov ah,CHAR_ALPHAN | CHAR_STD 0 00006446 3C15 cmp al,CTLU 0 00006448 7431 jz char_t100 ; Control-U and Control-T are treated 0 0000644A 3C14 cmp al,CTLT 0 0000644C 742D jz char_t100 ; as normal characters 0 0000644E B404 mov ah,CHAR_CTL ; Control Character 0 00006450 3C20 cmp al,' ' 0 00006452 7227 jb char_t100 858 0 00006454 B490 mov ah,CHAR_ALPHAN | CHAR_STD 0 00006456 3C30 cmp al,'0' 0 00006458 721F jb char_t90 ; Return SYMBOL 0 0000645A 3C39 cmp al,'9' 0 0000645C 761D jbe char_t100 ; Return AlphaNumeric 0 0000645E 3C41 cmp al,'A' 0 00006460 7217 jb char_t90 ; Return Symbol 0 00006462 3C5A cmp al,'Z' 0 00006464 7615 jbe char_t100 ; Return AlphaNumeric 0 00006466 3C61 cmp al,'a' 0 00006468 720F jb char_t90 ; Return Symbol 0 0000646A 3C7A cmp al,'z' 0 0000646C 760D jbe char_t100 ; Return AlphaNumeric 0 0000646E 3C80 cmp al,80h 0 00006470 7207 jb char_t90 ; Return Symbol 874 0 00006472 B408 mov ah, CHAR_KANJI ; assume character is 16 bits 0 00006474 E8[0000] call dbcs_lead ; is byte a DBCS lead? 0 00006477 7402 je char_t100 ; yes - done 878 char_t90: 0 00006479 B4A0 mov ah,CHAR_OTHER | CHAR_STD ; no - Normal Character Symbol 880 881 char_t100: 0 0000647B C3 ret 883 884 885 886 887 888 ; 889 ; CHAR_INFO will return various information about the character 890 ; at ES:SI 891 ; 892 ; On Entry: ES:SI Character Pointer 893 ; BX Current Column No. 894 ; CX Byte Scan Count 895 ; 896 ; On Exit: ES:SI Points to the next Character 897 ; BX Updates Column No. 898 ; CX Updates Byte Scan Count 899 ; AH Character type Flags 900 ; AL First byte of Character 901 char_info: 0 0000647C 26AC es lodsb 0 0000647E E8B7FF call char_type ; Test the character type and assume 0 00006481 43 inc bx ; it will take 1 Screen location 0 00006482 F6C431 test ah,CHAR_ONECOL 0 00006485 751F jnz char_i20 907 0 00006487 43 inc bx ; Now check for the Control Characters 0 00006488 F6C404 test ah,CHAR_CTL ; which take up 2 cols 0 0000648B 7519 jnz char_i20 911 0 0000648D F6C408 test ah,CHAR_KANJI ; If this was the first byte of a 0 00006490 7404 jz char_i10 ; KANJI character then skip the 0 00006492 46 inc si 0 00006493 49 dec cx ; next byte 0 00006494 EB10 jmp char_i20 917 918 char_i10: 0 00006496 50 push ax ; Save AX and calculate the number 0 00006497 4B dec bx 0 00006498 4B dec bx ; of screen locations that this TAB 0 00006499 89D8 mov ax,bx ; character will use based on the fact 0 0000649B 83E007 and ax,7 ; BX contains the current column 0 0000649E F7D8 neg ax 0 000064A0 83C008 add ax,8 0 000064A3 01C3 add bx,ax 0 000064A5 58 pop ax 928 929 char_i20: 0 000064A6 C3 ret 931 932 ; 933 ; CALC_CHARS calculates the number of character locations used 934 ; on the screen to display a particular sub-string of the current 935 ; buffer. This routine takes account of the Kanji, Control and TAB 936 ; characters. 937 ; 938 ; On Entry: SI Start Buffer Index 939 ; DI End Buffer Index 940 ; 941 ; On Exit: CX Count 942 ; 943 calc_chars: 0 000064A7 53 push bx 0 000064A8 56 push si 0 000064A9 57 push di 0 000064AA 8B5EF6 mov bx,[RL_INICOL] ; Get the initial Column 0 000064AD 29F7 sub di,si ; DI = Sub-string length bytes 0 000064AF 89F1 mov cx,si ; Use the Start Index for the 0 000064B1 8B76F8 mov si,[RL_BUFOFF] ; initial count and scan from the 0 000064B4 E305 jcxz calc_c20 ; start of the buffer 952 953 calc_c10: 0 000064B6 E8C3FF call char_info 0 000064B9 E2FB loop calc_c10 956 957 calc_c20: 0 000064BB 89F9 mov cx,di ; Sub-String Length 0 000064BD 89DF mov di,bx ; Current Column position 960 961 calc_c30: 0 000064BF E8BAFF call char_info 0 000064C2 E2FB loop calc_c30 964 0 000064C4 29FB sub bx,di 0 000064C6 89D9 mov cx,bx 0 000064C8 5F pop di 0 000064C9 5E pop si 0 000064CA 5B pop bx 0 000064CB C3 ret 971 972 ; 973 ; The following functions are purely Low level character output 974 ; functions. 975 ; 976 space_out: ; Write CX Space characters to the 0 000064CC B020 mov al,' ' ; Output handle 0 000064CE EB02 jmp block_out 979 980 bs_out: 0 000064D0 B008 mov al,CTLH ; Write CX BackSpace characters to 982 ;; jmp block_out ; Output Handle 983 984 block_out: 0 000064D2 E307 jcxz block_o20 0 000064D4 51 push cx 987 block_o10: 0 000064D5 E82D00 call write_char ; output this character 0 000064D8 E2FB loop block_o10 0 000064DA 59 pop cx 991 block_o20: 0 000064DB C3 ret 993 994 ; 995 ; Display CX characters from the string at ES:SI 996 ; 997 put_string: 0 000064DC E30D jcxz puts_s20 0 000064DE 51 push cx 0 000064DF 56 push si 1001 put_s10: 0 000064E0 51 push cx 0 000064E1 26AC es lodsb 0 000064E3 E80600 call put_char 0 000064E6 59 pop cx 0 000064E7 E2F7 loop put_s10 0 000064E9 5E pop si 0 000064EA 59 pop cx 1009 puts_s20: 0 000064EB C3 ret 1011 1012 ; 1013 ; Display the character in AL 1014 ; 1015 put_char: 0 000064EC 3C20 cmp al,' ' 0 000064EE 7315 jae write_char ; skip if it's printable 0 000064F0 3C14 cmp al,CTLT 0 000064F2 7411 je write_char ; Control-T and Control-U are treated 0 000064F4 3C15 cmp al,CTLU 0 000064F6 740D je write_char ; like normal Characters. 0 000064F8 3C09 cmp al,TAB 0 000064FA 7409 je write_char ; skip if it's TAB 0 000064FC 0C40 or al,040h ; Convert Character to Uppercase 0 000064FE 50 push ax ; save it 0 000064FF B05E mov al,'^' ; display the character 0 00006501 E80100 call write_char ; in ^X format 0 00006504 58 pop ax 1029 write_char: 0 00006505 06 push es 0 00006506 52 push dx 0 00006507 51 push cx 0 00006508 56 push si 0 00006509 57 push di 0 0000650A 50 push ax ; char on stack 0 0000650B 8B5EFC mov bx,[RL_OUTPUT] ; Output AL to the OUTPUT Handle 0 0000650E 16 push ss 0 0000650F 07 pop es ; ES:DX -> Character Buffer 0 00006510 89E6 mov si,sp ; buffer offset 0 00006512 B90100 mov cx,1 ; character count 0 00006515 E8[0000] call cooked_write ; Write Character 0 00006518 58 pop ax 0 00006519 5F pop di 0 0000651A 5E pop si 0 0000651B 59 pop cx 0 0000651C 5A pop dx 0 0000651D 07 pop es 0 0000651E C3 ret 1049 ; 1050 ; Read 1 a character from RL_INPUT saving all the vital registers 1051 ; from corruption. If the first character is the ESCAPE character 1052 ; set AH to TRUE and read the next byte. Otherwise AH is FALSE 1053 ; 1054 get_char: 0 0000651F 1E push ds 0 00006520 06 push es 0 00006521 52 push dx 0 00006522 56 push si 0 00006523 57 push di 1060 0 00006524 E8[0000] call get_dseg ; point at pcmode data 0 00006527 C536[0000] lds si,[con_device] ; DS:SI -> current console device 1063 DEVHDR.ATTRIB equ ATTRIB ; NASM port label 0 0000652B F744040040 test word [DEVHDR.ATTRIB + si],DA_IOCTL ; test bit 14: IOCTL bit 0 00006530 7427 jz get_c05 ; error if IOCTL not supported 0 00006532 83EC1E sub sp,RH_SIZE ; reserve this many words on the stack 0 00006535 89E3 mov bx,sp ; SS:BX -> request packet 0 00006537 16 push ss 0 00006538 07 pop es ; ES:BX -> request packet 0 00006539 8D56F4 lea dx,[RL_FLAGS] ; point at flags 0 0000653C 26C647020C mov byte [es:RH_CMD + bx],CMD_OUTPUT_IOCTL 0 00006541 26C6071E mov byte [es:RH_LEN + bx],RH4_LEN 0 00006545 2689570E mov [es:RH4_BUFOFF + bx],dx ; set up for a normal 0 00006549 268C5710 mov [es:RH4_BUFSEG + bx],ss ; IOCTL read/write 0 0000654D 26C747120200 mov word [es:RH4_COUNT + bx],2 0 00006553 E8[0000] call device_driver ; execute the command 0 00006556 83C41E add sp,RH_SIZE ; reclaim the stack 1078 get_c05: 1079 0 00006559 E8[0000] call get_dseg ; point at pcmode data 0 0000655C 8B5EFE mov bx,[RL_INPUT] ; BX = input stream 0 0000655F E8[0000] call cmdline_read ; get a character 1083 0 00006562 B400 mov ah,FALSE ; Assume this is NOT the Escape 0 00006564 2E3A06[0000] cmp al,[cs:esc_char] ; character and set high byte of the 0 00006569 7505 jnz get_c10 ; match word to FALSE 1087 0 0000656B E8[0000] call raw_read ; read the second byte of the escape 0 0000656E B401 mov ah,ESC_CODE ; sequence, setting high byte to ESC 1090 get_c10: 0 00006570 5F pop di 0 00006571 5E pop si 0 00006572 5A pop dx 0 00006573 07 pop es 0 00006574 1F pop ds 0 00006575 C3 ret 1097 1098 PCM_CODE ends 1099 === Switch to base=000000h -> "PCM_RODATA" 1100 section PCM_RODATA public align=2 class=CODE 1101 0 0000BA8A 00 esc_char db 0 ; Command Line Editor Escape Character 0 0000BA8B 2D00 edit_size dw (offset edit_end - edit_table)/EDIT_LEN 1104 0 0000BA8D 0D edit_table db CR 0 0000BA8E 00 db NESC_CODE 0 0000BA8F [4800] dw ret_string 1108 0 0000BA91 0A db LF 0 0000BA92 00 db NESC_CODE 0 0000BA93 [EA03] dw ignore_char 1112 0 0000BA95 08 db CTLH 0 0000BA96 00 db NESC_CODE 0 0000BA97 [5102] dw delp_char 1116 0 0000BA99 7F db DEL 0 0000BA9A 00 db NESC_CODE 0 0000BA9B [3F02] dw delf_char 1120 0 0000BA9D 1B db ESC 0 0000BA9E 00 db NESC_CODE 0 0000BA9F [AF02] dw del_line 1124 0 0000BAA1 3B db ';' 0 0000BAA2 01 db ESC_CODE 0 0000BAA3 [1903] dw copy_char ; Function 1 1128 0 0000BAA5 3C db '<' 0 0000BAA6 01 db ESC_CODE 0 0000BAA7 [2D03] dw copy_till_char ; Function 2 1132 0 0000BAA9 3D db '=' 0 0000BAAA 01 db ESC_CODE 0 0000BAAB [4903] dw copy_all ; Function 3 1136 0 0000BAAD 3E db '>' 0 0000BAAE 01 db ESC_CODE 0 0000BAAF [7C03] dw skip_till_char ; Function 4 1140 0 0000BAB1 3F db '?' 0 0000BAB2 01 db ESC_CODE 0 0000BAB3 [EB03] dw mem_line ; Function 5 1144 0 0000BAB5 40 db '@' 0 0000BAB6 01 db ESC_CODE 0 0000BAB7 [F103] dw eof_char ; Function 6 1148 0 0000BAB9 41 db 'A' 0 0000BABA 01 db ESC_CODE 0 0000BABB [F903] dw ctlat_char ; Function 7 1152 0 0000BABD 42 db 'B' 0 0000BABE 81 db ESC_CODE | DISABLE 0 0000BABF [0000] dw match_cmd ; Function 8 1156 0 0000BAC1 52 db 'R' 0 0000BAC2 01 db ESC_CODE 0 0000BAC3 [CB01] dw toggle_ins ; Insert 1160 0 0000BAC5 53 db 'S' 0 0000BAC6 01 db ESC_CODE 0 0000BAC7 [3F02] dw delf_char ; Delete 1164 0 0000BAC9 4B db 'K' 0 0000BACA 81 db ESC_CODE | DISABLE 0 0000BACB [0F02] dw prev_char ; Left Arrow 1168 0 0000BACD 4D db 'M' 0 0000BACE 81 db ESC_CODE | DISABLE 0 0000BACF [ED01] dw next_char ; Right Arrow 1172 1173 ; When advanced editing is disabled the match for Left/Right arrows will fall 1174 ; through to here 0 0000BAD1 4B db 'K' 0 0000BAD2 01 db ESC_CODE 0 0000BAD3 [5102] dw delp_char ; Left Arrow - compat 1178 0 0000BAD5 4D db 'M' 0 0000BAD6 01 db ESC_CODE 0 0000BAD7 [1903] dw copy_char ; Right Arrow - compat 1182 ; 1183 ; Extended functions from here on 1184 ; 0 0000BAD9 43 db 'C' 0 0000BADA 81 db ESC_CODE | DISABLE 0 0000BADB [0000] dw del_cur_history_buffer ; Func 9 1188 0 0000BADD 44 db 'D' 0 0000BADE 81 db ESC_CODE | DISABLE 0 0000BADF [0000] dw del_history_buffers ; Func 10 1192 0 0000BAE1 47 db 'G' 0 0000BAE2 81 db ESC_CODE | DISABLE 0 0000BAE3 [D901] dw goto_bol ; Home 1196 0 0000BAE5 4F db 'O' 0 0000BAE6 81 db ESC_CODE | DISABLE 0 0000BAE7 [0000] dw goto_eol ; End 1200 0 0000BAE9 74 db 't' 0 0000BAEA 81 db ESC_CODE | DISABLE 0 0000BAEB [0000] dw next_word ; Control Right Arrow 1204 0 0000BAED 73 db 's' 0 0000BAEE 81 db ESC_CODE | DISABLE 0 0000BAEF [0000] dw prev_word ; Control Left Arrow 1208 0 0000BAF1 16 db CTLV 0 0000BAF2 80 db NESC_CODE | DISABLE 0 0000BAF3 [CB01] dw toggle_ins 1212 0 0000BAF5 11 db CTLQ 0 0000BAF6 80 db NESC_CODE | DISABLE 0 0000BAF7 [D901] dw goto_bol 1216 0 0000BAF9 17 db CTLW 0 0000BAFA 80 db NESC_CODE | DISABLE 0 0000BAFB [0000] dw goto_eol 1220 0 0000BAFD 12 db CTLR 0 0000BAFE 80 db NESC_CODE | DISABLE 0 0000BAFF [0000] dw match_cmd 1224 0 0000BB01 04 db CTLD 0 0000BB02 80 db NESC_CODE | DISABLE 0 0000BB03 [ED01] dw next_char 1228 0 0000BB05 13 db CTLS 0 0000BB06 80 db NESC_CODE | DISABLE 0 0000BB07 [0F02] dw prev_char 0 0000BB09 06 db CTLF 0 0000BB0A 80 db NESC_CODE | DISABLE 0 0000BB0B [0000] dw next_word 1235 0 0000BB0D 01 db CTLA 0 0000BB0E 80 db NESC_CODE | DISABLE 0 0000BB0F [0000] dw prev_word 1239 0 0000BB11 07 db CTLG 0 0000BB12 80 db NESC_CODE | DISABLE 0 0000BB13 [5B02] dw deln_char 1243 0 0000BB15 14 db CTLT 0 0000BB16 80 db NESC_CODE | DISABLE 0 0000BB17 [0000] dw deln_word 1247 0 0000BB19 19 db CTLY 0 0000BB1A 80 db NESC_CODE | DISABLE 0 0000BB1B [AF02] dw del_line 1251 0 0000BB1D 02 db CTLB 0 0000BB1E 80 db NESC_CODE | DISABLE 0 0000BB1F [0000] dw del_bol 1255 0 0000BB21 0B db CTLK 0 0000BB22 80 db NESC_CODE | DISABLE 0 0000BB23 [4602] dw del_eol 1259 0 0000BB25 49 db 'I' 0 0000BB26 81 db ESC_CODE | DISABLE 0 0000BB27 [EA03] dw ignore_char ; PageUP 1263 0 0000BB29 51 db 'Q' 0 0000BB2A 81 db ESC_CODE | DISABLE 0 0000BB2B [EA03] dw ignore_char ; PageDown 1267 0 0000BB2D 48 db 'H' 0 0000BB2E 81 db ESC_CODE | DISABLE 0 0000BB2F [0000] dw prev_cmd ; Up Arrow 1271 0 0000BB31 50 db 'P' 0 0000BB32 81 db ESC_CODE | DISABLE 0 0000BB33 [0000] dw next_cmd ; Down Arrow 1275 0 0000BB35 05 db CTLE 0 0000BB36 80 db NESC_CODE | DISABLE 0 0000BB37 [0000] dw prev_cmd 1279 0 0000BB39 18 db CTLX 0 0000BB3A 80 db NESC_CODE | DISABLE 0 0000BB3B [0000] dw next_cmd 1283 0 0000BB3D 1F db CTLUB 0 0000BB3E 80 db NESC_CODE | DISABLE 0 0000BB3F [D001] dw toggle_search ; Default search mode 1287 edit_end label byte 1288 1289 PCM_RODATA ends 1290 === Switch to base=00C180h -> "PCMODE_DATA" 1291 section PCMODE_DATA public align=2 class=DATA 1292 1293 extrn con_device:dword ; Current Console Device 1294 extrn column:byte ; Console Cursor Location 1295 1296 ; savbuf_size equ 128 1297 savbuf_size equ CMDLINE_LEN 1298 1299 extrn savbuf:byte ; fixed location in DOS data area 1300 1301 extrn cle_state:word ; command line editing state 1302 PCMODE_DATA ends 1303 1304 end 1305 === Trace listing source: drdos/bin/history.lst 1 ; File : $HISTORY.ASM$ 2 ; 3 ; Description : 4 ; 5 ; Original Author : DIGITAL RESEARCH 6 ; 7 ; Last Edited By : $CALDERA$ 8 ; 9 ;-----------------------------------------------------------------------; 10 ; Copyright Work of Caldera, Inc. All Rights Reserved. 11 ; 12 ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL, 13 ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC. 14 ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES 15 ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF 16 ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO 17 ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE 18 ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE 19 ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED, 20 ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED, 21 ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST, 22 ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF 23 ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT 24 ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND 25 ; CIVIL LIABILITY. 26 ;-----------------------------------------------------------------------; 27 ; 28 ; *** Current Edit History *** 29 ; *** End of Current Edit History *** 30 ; 31 ; $Log$ 32 ; ENDLOG 33 ; 34 ; DOSPLUS Command Line Editor Routines 35 ; 36 37 group PCMCODE PCM_HISTORY 38 group PCMDATA PCMODE_DATA FDOS_DSEG GLOBAL_DATA 39 40 ASSUME DS:PCMDATA 41 42 [list -] 48 49 === Switch to base=000000h -> "PCM_HISTORY" 50 section PCM_HISTORY public align=2 class=CODE 51 52 public init_history, save_history 53 public del_history_buffers, del_cur_history_buffer 54 public prev_cmd, next_cmd, match_cmd, search_cmd 55 public prev_word, next_word, match_word 56 public goto_eol 57 public del_bol 58 public deln_word 59 60 extrn next_char:near 61 extrn save_line:near 62 extrn space_out:near 63 extrn bs_out:near 64 extrn goto_bol:near 65 extrn del_eol:near 66 extrn del_line:near 67 extrn char_info:near 68 extrn put_string:near 69 extrn prev_w20:near 70 extrn deln_w10:near 71 72 init_history: 73 ;------------ 74 ; On Entry: 75 ; SS:BP -> history structure 76 ; On Exit: 77 ; SS:SP filled in with appropriate history buffer 78 ; Preserve DX 79 ; 0 0000BC44 1E push ds 0 0000BC45 06 push es 0 0000BC46 16 push ss 0 0000BC47 07 pop es 0 0000BC48 8D7EE4 lea di,[RL_HIST_SEG] ; point at history buffer variables 0 0000BC4B BE[0000] mov si,offset histbuf1 ; assume root buffer 0 0000BC4E F746F48000 test word [RL_FLAGS],RLF_INROOT ; root task after all? 0 0000BC53 7503 jnz init_history10 ; if not we need to switch 0 0000BC55 BE[0000] mov si,offset histbuf2 ; application buffer 89 init_history10: 0 0000BC58 A5 movsw ; copy the seg 0 0000BC59 AD lodsw ; get overall length 0 0000BC5A 83E804 sub ax,2*2 ; last two words contain pointers 0 0000BC5D AB stosw ; save the working length 0 0000BC5E 96 xchg ax,si ; SI -> saved buffer positions 0 0000BC5F 8E5EE4 mov ds,[RL_HIST_SEG] ; in the buffer segment 0 0000BC62 A5 movsw ; update save and 0 0000BC63 A5 movsw ; recall positions 0 0000BC64 07 pop es 0 0000BC65 1F pop ds 0 0000BC66 C3 ret 101 102 103 save_history: 104 ;------------ 105 ; We are exiting from READLINE - if line has been modified save the 106 ; current line and update our pointers. 107 ; 0 0000BC67 85D2 test dx,dx ; skip update of sav/recall pointers 0 0000BC69 7421 jz save_history30 ; if empty line 0 0000BC6B E83700 call save_current ; save away current command line 0 0000BC6E 8B7EE8 mov di,[RL_HIST_SAVE] ; start with the old one 0 0000BC71 E89D01 call find_current_hist ; wrap it if we need to 0 0000BC74 E86501 call find_next_null ; find end of "new" command 0 0000BC77 47 inc di ; onto next character 0 0000BC78 3B7EE6 cmp di,[RL_HIST_SIZE] ; do we need to wrap ? 0 0000BC7B 7202 jb save_history10 0 0000BC7D 31FF xor di,di ; wrap the line 118 save_history10: 0 0000BC7F 897EE8 mov [RL_HIST_SAVE],di ; update "save" pointer 0 0000BC82 F746F42000 test word [RL_FLAGS],RLF_DIRTY ; if a line has been changed we'd 0 0000BC87 7403 jz save_history30 ; better update "recall" pointer 0 0000BC89 897EEA mov [RL_HIST_RECL],di ; too 123 save_history30: 0 0000BC8C 1E push ds 0 0000BC8D 06 push es 0 0000BC8E 16 push ss 0 0000BC8F 1F pop ds 0 0000BC90 8D76E8 lea si,[RL_HIST_SAVE] ; point at history buffer variables 0 0000BC93 8E46E4 mov es,[RL_HIST_SEG] 0 0000BC96 8B7EE6 mov di,[RL_HIST_SIZE] 0 0000BC99 A5 movsw ; save the "save" pointer 0 0000BC9A A5 movsw ; and the "recall" one 0 0000BC9B 07 pop es 0 0000BC9C 1F pop ds 0 0000BC9D C3 ret 136 137 save_current_if_dirty: 138 ;--------------------- 0 0000BC9E F746F42000 test word [RL_FLAGS],RLF_DIRTY ; if data is dirty (ie. user modified) 0 0000BCA3 7436 jz save_current20 ; then save it 141 save_current: 142 ;------------ 143 ; Copy current buffer contents to next free location in history buffer 144 ; 0 0000BCA5 56 push si 0 0000BCA6 57 push di 0 0000BCA7 52 push dx 0 0000BCA8 3B56E6 cmp dx,[RL_HIST_SIZE] ; is history buffer big enough ? 0 0000BCAB 732B jae save_current10 ; no, skip saving this line 0 0000BCAD E81001 call find_free_hist ; Find the next bit of space 0 0000BCB0 59 pop cx 0 0000BCB1 51 push cx ; CX = chars to save 0 0000BCB2 E324 jcxz save_current10 ; none, forget about it 0 0000BCB4 1E push ds 0 0000BCB5 06 push es 0 0000BCB6 C576F8 lds si,[RL_BUFPTR] 0 0000BCB9 8E46E4 mov es,[RL_HIST_SEG] 0 0000BCBC F3A4 rep movsb ; and save the data. 0 0000BCBE 31C0 xor ax,ax ; Null terminate it. 0 0000BCC0 AA stosb 0 0000BCC1 07 pop es 0 0000BCC2 1F pop ds 0 0000BCC3 57 push di 0 0000BCC4 E81501 call find_next_null ; Find the end of the entry we just 0 0000BCC7 89F9 mov cx,di ; overwrote - if any remains zap it 0 0000BCC9 5F pop di 0 0000BCCA FC cld 0 0000BCCB 31C0 xor ax,ax ; Null terminate this entry 0 0000BCCD 29F9 sub cx,di ; Figure out number of zeros to write 0 0000BCCF 7607 jbe save_current10 0 0000BCD1 06 push es 0 0000BCD2 8E46E4 mov es,[RL_HIST_SEG] 0 0000BCD5 F3AA rep stosb ; and pad to the next entry 0 0000BCD7 07 pop es 175 save_current10: 0 0000BCD8 5A pop dx 0 0000BCD9 5F pop di 0 0000BCDA 5E pop si 179 save_current20: 0 0000BCDB C3 ret 181 182 183 ; 184 ; Here is the code to deal with history buffers 185 ; 186 ; match_cmd Does a string search based on what the user has typed so far 187 ; search_cmd Matches string, but doesn't change match state 188 ; prev_cmd Retrieves the previous command from the history buffer 189 ; next_cmd " " next " " " " " 190 ; 191 match_cmd: 0 0000BCDC A0[0000] mov al,[@hist_flg] ; is matching enabled ? 0 0000BCDF 83E008 and ax,RLF_MATCH 0 0000BCE2 7408 jz search_cmd ; no, always match 0 0000BCE4 3146F4 xor [RL_FLAGS],ax ; toggle match bit 0 0000BCE7 8546F4 test [RL_FLAGS],ax ; turning matching off ? 0 0000BCEA 7458 jz match30 ; then just exit 198 search_cmd: 0 0000BCEC 8976EC mov [RL_SAVPOS],si ; any chars to save ? 0 0000BCEF 85F6 test si,si 0 0000BCF1 7452 jz prev_cmd ; blank line - just get previous 0 0000BCF3 E8A8FF call save_current_if_dirty ; save current line if it needs saving 0 0000BCF6 56 push si ; save current offset in line 0 0000BCF7 57 push di 0 0000BCF8 52 push dx ; Save index to end of current line 0 0000BCF9 89F2 mov dx,si ; discard rest of line if no match 0 0000BCFB 8B7EEA mov di,[RL_HIST_RECL] ; Point to the current entry 208 match_loop: 0 0000BCFE E8EB00 call find_prev_hist ; DI-> previous cmd in buffer 0 0000BD01 57 push di ; save this command position 0 0000BD02 8B7EEA mov di,[RL_HIST_RECL] ; get starting position 0 0000BD05 E80901 call find_current_hist ; handle any wrapping 0 0000BD08 5E pop si ; recover previous command 0 0000BD09 39F7 cmp di,si ; have we been all round ? 0 0000BD0B 7414 je match_error ; YES - We've looped so no match found 0 0000BD0D 1E push ds 0 0000BD0E 56 push si ; save this entry 0 0000BD0F 8E5EE4 mov ds,[RL_HIST_SEG] 0 0000BD12 8B7EF8 mov di,[RL_BUFOFF] ; ES:DI -> match string 0 0000BD15 8B4EEC mov cx,[RL_SAVPOS] ; try to match CX characters 0 0000BD18 F3A6 repe cmpsb 0 0000BD1A 5F pop di ; recover this entry 0 0000BD1B 1F pop ds 0 0000BD1C 75E0 jne match_loop ; try again if we didn't match 0 0000BD1E E86C00 call copy_from_hist ; if it did match copy it 226 match_error: 0 0000BD21 59 pop cx ; Get end of displayed line 0 0000BD22 5F pop di ; user's buffer 0 0000BD23 5E pop si 0 0000BD24 56 push si ; save current position in lines 0 0000BD25 E8[0000] call space_out ; Rub the displayed line out 0 0000BD28 E8[0000] call bs_out ; And backspace to it's start 0 0000BD2B E84E00 call goto_eol ; display the line 0 0000BD2E E8[0000] call goto_bol ; Move cursor to begining 0 0000BD31 59 pop cx ; CX = end of matched portion 0 0000BD32 894EEC mov [RL_SAVPOS],cx ; CX = Current position in command 0 0000BD35 E307 jcxz match20 238 match10: ; Move cursor forward to current 0 0000BD37 51 push cx ; position 0 0000BD38 E8[0000] call next_char ; next_char destroys our loop count 0 0000BD3B 59 pop cx ; so keep it 0 0000BD3C E2F9 loop match10 243 match20: 0 0000BD3E 8B4EEE mov cx,[RL_SAVMAX] ; we can't copy any more 0 0000BD41 894EEC mov [RL_SAVPOS],cx 246 match30: 0 0000BD44 C3 ret 248 249 250 prev_cmd: 251 ; Get the previous command from the buffer 0 0000BD45 F746F41000 test word [RL_FLAGS],RLF_RECALLED ; is this the 1st recall ? 0 0000BD4A 750D jnz prev_cmd10 0 0000BD4C 51 push cx 0 0000BD4D 57 push di 0 0000BD4E 8B7EE8 mov di,[RL_HIST_SAVE] ; get existing "save" ptr 0 0000BD51 E8BD00 call find_current_hist ; wrap it if we need to 0 0000BD54 897EEA mov [RL_HIST_RECL],di ; and update "recall" pointer 0 0000BD57 5F pop di 0 0000BD58 59 pop cx 261 prev_cmd10: 0 0000BD59 E842FF call save_current_if_dirty ; save current line if it needs saving 0 0000BD5C E8[0000] call del_line ; then delete it 0 0000BD5F 56 push si 0 0000BD60 57 push di 0 0000BD61 8B7EEA mov di,[RL_HIST_RECL] ; point to the current entry 0 0000BD64 E88500 call find_prev_hist ; DI -> previous entry 0 0000BD67 EB0E jmp found_cmd ; now go and copy it to the user buffer 269 270 next_cmd: 271 ; Get the next command from the buffer 0 0000BD69 E832FF call save_current_if_dirty ; save current line if it needs saving 0 0000BD6C E8[0000] call del_line ; then delete it 0 0000BD6F 56 push si 0 0000BD70 57 push di 0 0000BD71 8B7EEA mov di,[RL_HIST_RECL] ; point to the current entry 0 0000BD74 E89400 call find_next_hist ; DI -> next entry 278 ; jmp found_cmd ; now go and copy it to the user buffer 279 280 found_cmd: 0 0000BD77 E81300 call copy_from_hist ; Copy from history to user buffer 0 0000BD7A 5F pop di 0 0000BD7B 5E pop si 284 ; jmp goto_eol ; Display new line. 285 286 goto_eol: ; Move the cursor to the end of the 0 0000BD7C 89D1 mov cx,dx 0 0000BD7E 29F1 sub cx,si ; displayed line 0 0000BD80 E30A jcxz goto_e10 ; Already at the EOL 0 0000BD82 0376F8 add si,[RL_BUFOFF] ; Get the Offset in the buffer 0 0000BD85 E8[0000] call put_string ; Output the sub_string 0 0000BD88 01CF add di,cx ; Update the local variables 0 0000BD8A 89D6 mov si,dx ; and return 294 goto_e10: 0 0000BD8C C3 ret 296 297 ; DI-> Current entry in history buffer 298 ; 299 copy_from_hist: 0 0000BD8D 834EF410 or word [RL_FLAGS],RLF_RECALLED ; remember we have recalled something 0 0000BD91 8366F4DF and word [RL_FLAGS],~ RLF_DIRTY ; this entry is already in buffers 0 0000BD95 897EEA mov [RL_HIST_RECL],di ; update pointer for next time 0 0000BD98 E84100 call find_next_null ; how big is this entry ? 0 0000BD9B 89F9 mov cx,di 0 0000BD9D 8B76EA mov si,[RL_HIST_RECL] 0 0000BDA0 29F1 sub cx,si ; (CX-SI)=No of bytes to copy 0 0000BDA2 3B4EF2 cmp cx,[RL_MAXLEN] ; is the line bigger than our buffer ? 0 0000BDA5 7203 jb copy_from_hist1 ; if so we want to clip it 0 0000BDA7 8B4EF2 mov cx,[RL_MAXLEN] ; to the maximum possible value 310 copy_from_hist1: 0 0000BDAA 89CA mov dx,cx 0 0000BDAC 1E push ds 0 0000BDAD 8E5EE4 mov ds,[RL_HIST_SEG] 0 0000BDB0 8B7EF8 mov di,[RL_BUFOFF] 0 0000BDB3 F3A4 rep movsb ; copy to line buffer 0 0000BDB5 1F pop ds 0 0000BDB6 E8[0000] call save_line ; save the line 0 0000BDB9 8B4EEE mov cx,[RL_SAVMAX] ; we can't copy any more 0 0000BDBC 894EEC mov [RL_SAVPOS],cx 0 0000BDBF C3 ret 321 322 ; Some primitives for history buffer handling: 323 ; 324 ; find_free_hist Find the next free entry in the history buffer 325 ; find_next_null Finds the end of the current entry 326 ; find_prev_hist Finds the start of the previous entry 327 ; find_next_hist Finds the start of the next entry 328 ; find_current_hist Finds the start of current entry 329 330 ; 331 ; Make DI-> next entry of sufficient length for the current cmd buffer 332 ; If we can't fit at the end zero the remainder of the buffer then wrap 333 ; back to the start. 334 ; 335 336 find_free_hist: 0 0000BDC0 8B7EE8 mov di,[RL_HIST_SAVE] ; Point at current last entry 0 0000BDC3 57 push di ; Will DX bytes fit? 0 0000BDC4 01D7 add di,dx 0 0000BDC6 3B7EE6 cmp di,[RL_HIST_SIZE] ; Did we run out of buffer? 0 0000BDC9 5F pop di 0 0000BDCA 720F jb find_free_hist20 0 0000BDCC 31C0 xor ax,ax ; doesn't fit, so zero to end of buffer 344 find_free_hist10: 0 0000BDCE 06 push es 0 0000BDCF 8E46E4 mov es,[RL_HIST_SEG] 0 0000BDD2 AA stosb ; keep on zeroing 0 0000BDD3 07 pop es 0 0000BDD4 3B7EE6 cmp di,[RL_HIST_SIZE] 0 0000BDD7 72F5 jb find_free_hist10 0 0000BDD9 31FF xor di,di ; wrap back to start of history buffer 352 find_free_hist20: 0 0000BDDB C3 ret 354 355 ; Entry DI-> entry in the history buffer 356 ; Make DI-> next NULL in the history buffer ( end of current entry ) 357 ; 358 find_next_null: 0 0000BDDC 8B4EE6 mov cx,[RL_HIST_SIZE] 0 0000BDDF 29F9 sub cx,di ; Calc no of bytes left 0 0000BDE1 31C0 xor ax,ax ; Look for next terminator 0 0000BDE3 06 push es 0 0000BDE4 8E46E4 mov es,[RL_HIST_SEG] 0 0000BDE7 F2AE repnz scasb 0 0000BDE9 4F dec di ; point at the NUL 0 0000BDEA 07 pop es 0 0000BDEB C3 ret 368 369 ; Entry DI-> entry in the history buffer 370 ; Make DI-> previous entry in the history buffer 371 ; Preserve CX 372 find_prev_hist: 0 0000BDEC E82200 call find_current_hist ; handle any wrapping 0 0000BDEF 89F8 mov ax,di ; AX = entry we want previous for 375 find_prev_hist10: 0 0000BDF1 50 push ax ; save current offset 0 0000BDF2 57 push di ; save initial offset 0 0000BDF3 97 xchg ax,di ; find next from here until 0 0000BDF4 E81400 call find_next_hist ; we get back where we started 0 0000BDF7 97 xchg ax,di ; AX = current offset 0 0000BDF8 5F pop di ; recover initial value 0 0000BDF9 5B pop bx ; recover previous offset 0 0000BDFA 39F8 cmp ax,di ; have we wrapped yet ? 0 0000BDFC 740A je find_prev_hist20 ; yes, BX = previous entry 0 0000BDFE 77F1 ja find_prev_hist10 ; we are above target so continue 0 0000BE00 39FB cmp bx,di ; we are below target - if previous 0 0000BE02 73ED jae find_prev_hist10 ; was above target we are OK 0 0000BE04 39D8 cmp ax,bx ; if new below previous then we 0 0000BE06 73E9 jnb find_prev_hist10 ; have ERROR wrap, so stop 390 find_prev_hist20: 0 0000BE08 89DF mov di,bx ; DI -> Previous entry 0 0000BE0A C3 ret 393 394 find_next_hist: 0 0000BE0B E80300 call find_current_hist ; handle any wrapping 0 0000BE0E E8CBFF call find_next_null ; point to end of current entry 397 ; jmp find_current_hist ; handle any wrapping 398 399 find_current_hist: 400 ; This routine is complicated by the need to handle switchers, where 401 ; our buffers and pointers may get out of step 0 0000BE11 06 push es 0 0000BE12 31C0 xor ax,ax 0 0000BE14 8E46E4 mov es,[RL_HIST_SEG] ; now work backwards to start of line 405 find_current_hist10: 0 0000BE17 83FF01 cmp di,1 ; are we at the start of the buffer 0 0000BE1A 7211 jb find_current_hist30 ; then don't wrap 0 0000BE1C FD std 0 0000BE1D AE scasb ; is previous char a NUL ? 0 0000BE1E FC cld ; (it should be!) 0 0000BE1F 75F6 jne find_current_hist10 0 0000BE21 47 inc di ; ES:DI -> 1st char of line 413 find_current_hist20: 0 0000BE22 8B4EE6 mov cx,[RL_HIST_SIZE] 0 0000BE25 29F9 sub cx,di ; CX= Remaining no: of bytes in buffer 0 0000BE27 7604 jbe find_current_hist30 0 0000BE29 F3AE repe scasb ; skip over zero's 0 0000BE2B 7503 jne find_current_hist40 419 find_current_hist30: 0 0000BE2D BF0100 mov di,1 ; wrap to start of buffer 421 find_current_hist40: 0 0000BE30 4F dec di 0 0000BE31 07 pop es 0 0000BE32 C3 ret 425 426 del_history_buffers: 427 ;------------------- 428 ; Delete contents of both history buffers 429 ; 0 0000BE33 A1[0000] mov ax,[histbuf1] ; Segment of 1st history buffer 0 0000BE36 8B0E[0000] mov cx,[histsiz1] ; End of 1st history buffer 0 0000BE3A E80F00 call zap_buffer 0 0000BE3D A1[0000] mov ax,[histbuf2] ; Segment of 2nd history buffer 0 0000BE40 8B0E[0000] mov cx,[histsiz2] ; End of 2nd history buffer 0 0000BE44 EB06 jmp zap_buffer 436 437 del_cur_history_buffer: 438 ;---------------------- 439 ; Delete contents of the current history buffer 440 ; 0 0000BE46 8B46E4 mov ax,[RL_HIST_SEG] ; zero the current buffer 0 0000BE49 8B4EE6 mov cx,[RL_HIST_SIZE] 443 zap_buffer: 0 0000BE4C 06 push es ; zero fill CX bytes at AX:0 0 0000BE4D 57 push di 0 0000BE4E 8EC0 mov es,ax 0 0000BE50 31C0 xor ax,ax 0 0000BE52 8946EA mov [RL_HIST_RECL],ax 0 0000BE55 8946E8 mov [RL_HIST_SAVE],ax 0 0000BE58 31FF xor di,di 0 0000BE5A F3AA rep stosb ; zero fill the buffer 0 0000BE5C 5F pop di 0 0000BE5D 07 pop es 0 0000BE5E E8[0000] call del_line ; then delete current line 0 0000BE61 E9[0000] jmp save_line 456 457 458 next_word: 0 0000BE64 89D1 mov cx,dx ; Calculate the number of bytes 0 0000BE66 29F1 sub cx,si ; left to scan 0 0000BE68 E314 jcxz next_w10 ; Skip if at the EOL 0 0000BE6A 56 push si ; Save the current Index 0 0000BE6B 89FE mov si,di ; Scan from the current location 0 0000BE6D E80F00 call match_word ; Get the next word boundary 0 0000BE70 89F1 mov cx,si 0 0000BE72 29F9 sub cx,di ; Calculate the string length 0 0000BE74 89FE mov si,di ; to be displayed from the current 0 0000BE76 E8[0000] call put_string ; location and output the data 0 0000BE79 5E pop si 0 0000BE7A 01CE add si,cx ; Update the Index and Offset pointers 0 0000BE7C 01CF add di,cx 472 next_w10: 0 0000BE7E C3 ret 474 475 ; 476 ; MATCH_WORD scans the buffer at ES:SI for word boundaries 477 ; and returns to the calling routine whenever it detects such 478 ; a boundary. 479 ; 480 ; On Entry: ES:SI Buffer Address 481 ; CX Maximum No of bytes to Scan 482 ; 483 ; On Exit: ES:SI Next Word Boundary 484 ; 485 match_word: 0 0000BE7F E8[0000] call char_info 0 0000BE82 F6C418 test ah,CHAR_ALPHAN | CHAR_KANJI 0 0000BE85 E0F8 loopnz match_word ; scan the rest of the current word 0 0000BE87 E314 jcxz match_w30 ; end of word or kanji ? 490 0 0000BE89 52 push dx 492 match_w10: 0 0000BE8A 89F2 mov dx,si 0 0000BE8C E8[0000] call char_info 0 0000BE8F F6C418 test ah,CHAR_ALPHAN | CHAR_KANJI 0 0000BE92 E1F6 loopz match_w10 0 0000BE94 7406 jz match_w20 0 0000BE96 29D6 sub si,dx ; Correct the count in CX 0 0000BE98 01F1 add cx,si ; and return the location of the 0 0000BE9A 89D6 mov si,dx ; word boundary 501 502 match_w20: 0 0000BE9C 5A pop dx 504 match_w30: 0 0000BE9D C3 ret 506 507 prev_word: 0 0000BE9E 89F1 mov cx,si 0 0000BEA0 E3FB jcxz match_w30 ; Initialize the count 0 0000BEA2 52 push dx 0 0000BEA3 56 push si 0 0000BEA4 57 push di 0 0000BEA5 8B76F8 mov si,[RL_BUFOFF] ; Scan from the begining of the buffer 0 0000BEA8 89F2 mov dx,si ; keeping the last match in DX 515 prev_w10: 0 0000BEAA E8D2FF call match_word ; Find the next word boundary 0 0000BEAD E304 jcxz prev_w15 ; Stop when we get to the current offset 0 0000BEAF 89F2 mov dx,si ; Save current location 0 0000BEB1 EBF7 jmp prev_w10 ; and repeat 520 prev_w15: 0 0000BEB3 E9[0000] jmp prev_w20 522 523 del_bol: ; Delete to the begining of the line 0 0000BEB6 09F6 or si,si 0 0000BEB8 740C jz del_bol10 ; Ignore if at the begining 0 0000BEBA 09D2 or dx,dx 0 0000BEBC 7408 jz del_bol10 ; Or the line is empty 0 0000BEBE 57 push di ; Save the current index 0 0000BEBF E8[0000] call goto_bol ; Move to the start of the line 0 0000BEC2 59 pop cx ; Restore the current offset 0 0000BEC3 E9[0000] jmp deln_w10 ; and jump to common code 532 del_bol10: 0 0000BEC6 C3 ret 534 535 deln_word: 0 0000BEC7 89D1 mov cx,dx ; Calculate the number of bytes 0 0000BEC9 29F1 sub cx,si ; left to scan 0 0000BECB E3F9 jcxz del_bol10 ; Skip if at the EOL 0 0000BECD 56 push si ; Save the current Index 0 0000BECE 89FE mov si,di ; Scan from the current location 0 0000BED0 E8ACFF call match_word ; Get the next word boundary 0 0000BED3 89F1 mov cx,si 0 0000BED5 5E pop si 0 0000BED6 E9[0000] jmp deln_w10 545 546 PCM_HISTORY ends 547 === Switch to base=00C180h -> "PCMODE_DATA" 548 section PCMODE_DATA public align=2 class=DATA 549 550 extrn @hist_flg:byte ; To select between histbufs 1 or 2 551 552 PCMODE_DATA ends 553 === Switch to base=00C180h -> "GLOBAL_DATA" 554 section GLOBAL_DATA public align=2 class=DATA 555 556 extrn histbuf1:word, histsiz1:word, histbuf2:word, histsiz2:word 557 558 GLOBAL_DATA ends 559 560 end 561 === Trace listing source: drdos/bin/dos7.lst 1 ; DOS7.ASM - Functions for DOS 7 compatibility 2 ; 3 ; This file is part of 4 ; The DR-DOS/OpenDOS Enhancement Project - http://www.drdosprojects.de 5 ; Copyright (c) 2002-2009 Udo Kuhnt 6 7 group PCMDATA PCMODE_DATA FDOS_DSEG 8 group PCMCODE PCM_CODE 9 10 ASSUME DS:PCMDATA 11 12 [list -] 18 === Switch to base=000000h -> "PCM_CODE" 19 section PCM_CODE public align=1 class=CODE 20 21 extrn get_path_drive:near 22 extrn fdos_diskinfo:near 23 extrn fdos_nocrit:near 24 extrn mul32:near 25 extrn return_AX_CLC:near 26 extrn error_exit:near 27 extrn get_dseg:near 28 29 public func73 30 func73: 0 00006576 3C02 cmp al,2 ; function 7302h? 0 00006578 7411 je func7302 ; yes 0 0000657A 3C03 cmp al,3 ; function 7303h? 0 0000657C 7503 jne f73_10 0 0000657E E9B400 jmp func7303 ; yes 36 f73_10: 0 00006581 3C05 cmp al,5 ; function 7305h? 0 00006583 7503 jne func73_error 0 00006585 E9AD01 jmp func7305 ; yes 40 func73_error: 0 00006588 31C0 xor ax,ax ; function not supported 0 0000658A C3 ret 43 44 ; ************************************* 45 ; *** DOS Function 7302h *** 46 ; *** Get Extended DPB *** 47 ; ************************************* 48 ; 49 ;Entry: DL = drive number 50 ; ES:DI = pointer to buffer for Extended DPB structure 51 ; CX = length of buffer 52 ;Exit: ES:DI preserved 53 ; CF clear 54 ;Error: CF set 55 ; AX = error code 56 57 func7302: 0 0000658B 83F93F cmp cx,EDPB_LEN+2 ; enough buffer space for data? 0 0000658E 7307 jae f7302_10 0 00006590 B8E8FF mov ax,-18h ; return 18h (bad request structure length) 0 00006593 F9 stc 0 00006594 E9[0000] jmp error_exit ; no, then exit with error 63 f7302_10: 0 00006597 30F6 xor dh,dh 65 fdos_DISKINFO equ fdos_diskinfo ; NASM port label 0 00006599 E8[0000] call fdos_DISKINFO ; get drive info, ES:BX -> DDSC 0 0000659C 7307 jnc f7302_20 0 0000659E B8F1FF mov ax,-0fh ; return 0fh (invalid drive) 0 000065A1 F9 stc 0 000065A2 E9[0000] jmp error_exit ; error if invalid drive 71 f7302_20: 0 000065A5 1E push ds 0 000065A6 C52E[0000] lds bp,[int21regs_ptr] ; DS:DI -> Extended DPB structure 0 000065AA 3E8B7E0A mov di,[ds:reg_DI + bp] 0 000065AE 3E8B7608 mov si,[ds:reg_SI + bp] ; SI = signature 0 000065B2 3E8E5E10 mov ds,[ds:reg_ES + bp] 0 000065B6 C7053D00 mov word ptr [di],EDPB_LEN ; length of data 0 000065BA 47 inc di ; skip to begin of EDPB 0 000065BB 47 inc di 0 000065BC 1E push ds 0 000065BD 06 push es 0 000065BE 1F pop ds 0 000065BF 07 pop es ; ES:DI -> EDPB, DS:BX -> DDSC 0 000065C0 56 push si 0 000065C1 57 push di 0 000065C2 89DE mov si,bx ; copy standard DPB from DDSC 0 000065C4 B92100 mov cx,DDSC_BFREE 0 000065C7 F3A4 rep movsb 0 000065C9 5F pop di 0 000065CA 5E pop si 0 000065CB 30F6 xor dh,dh 0 000065CD 26887518 mov [es:EDPB_DPBFLAGS + di],dh ; clear DBP flags 0 000065D1 81FEA6F1 cmp si,0f1a6h ; check signature 0 000065D5 7413 je f7302_25 0 000065D7 31C0 xor ax,ax ; wrong signature, clear driver header and link address fields 0 000065D9 48 dec ax 0 000065DA 26894513 mov word ptr [es:EDPB_DEVHEAD + di],ax 0 000065DE 26894515 mov word ptr [es:EDPB_DEVHEAD+2 + di],ax 0 000065E2 26894519 mov word ptr [es:EDPB_LINK + di],ax 0 000065E6 2689451B mov word ptr [es:EDPB_LINK+2 + di],ax 101 f7302_25: 0 000065EA 8D7721 lea si,[DDSC_BFREE + bx] 0 000065ED B91E00 mov cx,DDSC_FSVER-DDSC_BFREE 0 000065F0 837F0900 cmp word [DDSC_DIRENT + bx],0 ; is this a FAT32 drive? 0 000065F4 7507 jnz f7302_30 ; no, then build the remaining portion from scratch 0 000065F6 83C71F add di,DDSC_FREE 0 000065F9 F3A4 rep movsb ; else copy remaining EDPB portion from DDSC 0 000065FB EB30 jmp f7302_40 109 f7302_30: 0 000065FD 57 push di 0 000065FE 83C71F add di,DDSC_FREE 0 00006601 30C0 xor al,al ; zero contents of remaining EDPB part 0 00006603 F3AA rep stosb 0 00006605 5F pop di 0 00006606 31C0 xor ax,ax ; AX=FFFFh 0 00006608 48 dec ax 0 00006609 26894525 mov [es:EDPB_FSINFO + di],ax ; then fill in the 16-bit values 0 0000660D 26894527 mov [es:EDPB_BOOTBAK + di],ax 0 00006611 8B470B mov ax,word ptr [DDSC_DATADDR + bx] 0 00006614 26894529 mov word ptr [es:EDPB_BDATADDR + di],ax 0 00006618 8B470D mov ax,word ptr [DDSC_NCLSTRS + bx] 0 0000661B 2689452D mov word ptr [es:EDPB_BCLSTRS + di],ax 0 0000661F 8B470F mov ax,word ptr [DDSC_NFATRECS + bx] 0 00006622 26894531 mov word ptr [es:EDPB_BFATRECS + di],ax 0 00006626 8B471D mov ax,word ptr [DDSC_BLOCK + bx] 0 00006629 26894539 mov word ptr [es:EDPB_BBLOCK + di],ax 127 f7302_40: 0 0000662D 1F pop ds 0 0000662E 31C0 xor ax,ax 0 00006630 E8[0000] call return_AX_CLC 0 00006633 F8 clc 132 f7302_exit: 0 00006634 C3 ret 134 135 ; ************************************* 136 ; *** DOS Function 7303h *** 137 ; *** Extended Free Disk Space *** 138 ; ************************************* 139 ; 140 ;Entry: DS:DX = pointer to ASCIZ string for path 141 ; ES:DI = pointer to buffer for extended free space structure 142 ; CX = length of buffer 143 ;Exit: ES:DI preserved 144 ; CF clear 145 ;Error: CF set 146 ; AX = error code 147 148 func7303: 0 00006635 C42E[0000] les bp,[int21regs_ptr] ; ES:DI = pointer to drive path 0 00006639 268B7E06 mov di,[es:reg_DX + bp] 0 0000663D 268E460E mov es,[es:reg_DS + bp] 0 00006641 E8[0000] call get_path_drive 0 00006644 7307 jnc f7303_10 0 00006646 B8F1FF mov ax,-0fh ; return 0fh (invalid drive) 0 00006649 F9 stc 0 0000664A E9[0000] jmp error_exit ; error if invalid drive 157 f7303_10: 0 0000664D 88C2 mov dl,al ; drive number 0 0000664F FEC2 inc dl 0 00006651 30F6 xor dh,dh 0 00006653 E8[0000] call fdos_DISKINFO ; get drive info, ES:BX -> DDSC 0 00006656 7307 jnc f7303_20 0 00006658 B8F1FF mov ax,-0fh ; return 0fh (invalid drive) 0 0000665B F9 stc 0 0000665C E9[0000] jmp error_exit ; error if invalid drive 166 f7303_20: 0 0000665F 83F924 cmp cx,FREED_LEN ; enough buffer space for data? 0 00006662 7607 jbe f7303_30 0 00006664 B8E8FF mov ax,-18h ; return 18h (bad request structure length) 0 00006667 F9 stc 0 00006668 E9[0000] jmp error_exit ; no, then exit with error 172 f7303_30: 0 0000666B 1E push ds 0 0000666C C52E[0000] lds bp,[int21regs_ptr] ; DS:DI -> free space structure 0 00006670 3E8B7E0A mov di,[ds:reg_DI + bp] 0 00006674 3E8E5E10 mov ds,[ds:reg_ES + bp] 0 00006678 31D2 xor dx,dx 0 0000667A B82400 mov ax,FREED_LEN ; length of data 0 0000667D 8905 mov [FREED_SIZE + di],ax 0 0000667F 31C0 xor ax,ax ; structure version 0 00006681 894502 mov [FREED_VER + di],ax 0 00006684 30E4 xor ah,ah ; sector per cluster 0 00006686 268A4704 mov al,[es:DDSC_CLMSK + bx] ; this is minus one 0 0000668A 40 inc ax ; so add one again 0 0000668B 894504 mov word ptr [FREED_SECPCLUS + di],ax 0 0000668E 895506 mov word ptr [FREED_SECPCLUS+2 + di],dx 0 00006691 268B4702 mov ax,[es:DDSC_SECSIZE + bx] ; bytes per sector 0 00006695 894508 mov word ptr [FREED_BYTEPSEC + di],ax 0 00006698 89550A mov word ptr [FREED_BYTEPSEC+2 + di],dx 0 0000669B 26837F0900 cmp word [es:DDSC_DIRENT + bx],0 ; is this a FAT32 drive? 0 000066A0 7423 je f7303_40 ; yes 0 000066A2 268B471F mov ax,[es:DDSC_FREE + bx] ; free clusters on drive (16-bit) 0 000066A6 89450C mov word ptr [FREED_FREECL + di],ax 0 000066A9 89451C mov word ptr [FREED_FREEPCL + di],ax 0 000066AC 89550E mov word ptr [FREED_FREECL+2 + di],dx 0 000066AF 89551E mov word ptr [FREED_FREEPCL+2 + di],dx 0 000066B2 268B470D mov ax,[es:DDSC_NCLSTRS + bx] ; highest cluster on drive (16-bit) 0 000066B6 48 dec ax ; total clusters (16-bit) 0 000066B7 894510 mov word ptr [FREED_NCLUSTER + di],ax 0 000066BA 894520 mov word ptr [FREED_NPCLUS + di],ax 0 000066BD 895512 mov word ptr [FREED_NCLUSTER+2 + di],dx 0 000066C0 895522 mov word ptr [FREED_NPCLUS+2 + di],dx 0 000066C3 EB2E jmp f7303_50 204 f7303_40: 0 000066C5 268B4721 mov ax,word ptr [es:DDSC_BFREE + bx] ; free clusters on drive (32-bit) 0 000066C9 89450C mov word ptr [FREED_FREECL + di],ax 0 000066CC 89451C mov word ptr [FREED_FREEPCL + di],ax 0 000066CF 268B4723 mov ax,word ptr [es:DDSC_BFREE+2 + bx] 0 000066D3 89450E mov word ptr [FREED_FREECL+2 + di],ax 0 000066D6 89451E mov word ptr [FREED_FREEPCL+2 + di],ax 0 000066D9 268B472F mov ax,word ptr [es:DDSC_BCLSTRS + bx] ; highest cluster on drive (32-bit) 0 000066DD 268B5731 mov dx,word ptr [es:DDSC_BCLSTRS+2 + bx] 0 000066E1 83E801 sub ax,1 ; total clusters (32-bit) 0 000066E4 83DA00 sbb dx,0 0 000066E7 894510 mov word ptr [FREED_NCLUSTER + di],ax 0 000066EA 894520 mov word ptr [FREED_NPCLUS + di],ax 0 000066ED 895512 mov word ptr [FREED_NCLUSTER+2 + di],dx 0 000066F0 895522 mov word ptr [FREED_NPCLUS+2 + di],dx 219 f7303_50: 0 000066F3 FF751E push word ptr [FREED_FREEPCL+2 + di] ; number of free physical clusters 0 000066F6 FF751C push word ptr [FREED_FREEPCL + di] 0 000066F9 FF7506 push word ptr [FREED_SECPCLUS+2 + di] ; number of sectors per cluster 0 000066FC FF7504 push word ptr [FREED_SECPCLUS + di] 0 000066FF 83EC08 sub sp,8 ; reserve space on stack 0 00006702 E8[0000] call mul32 ; multiply these values 0 00006705 58 pop ax ; to get free physical sectors 0 00006706 894514 mov word ptr [FREED_FREESEC + di],ax 0 00006709 58 pop ax 0 0000670A 894516 mov word ptr [FREED_FREESEC+2 + di],ax 0 0000670D 83C40C add sp,12 ; clean up the stack again 0 00006710 FF7522 push word ptr [FREED_NPCLUS+2 + di] ; number of total physical clusters 0 00006713 FF7520 push word ptr [FREED_NPCLUS + di] 0 00006716 FF7506 push word ptr [FREED_SECPCLUS+2 + di] ; number of sectors per cluster 0 00006719 FF7504 push word ptr [FREED_SECPCLUS + di] 0 0000671C 83EC08 sub sp,8 ; reserve space on stack 0 0000671F E8[0000] call mul32 ; multiply these values 0 00006722 58 pop ax ; to get total physical sectors 0 00006723 894518 mov word ptr [FREED_NSECS + di],ax 0 00006726 58 pop ax 0 00006727 89451A mov word ptr [FREED_NSECS+2 + di],ax 0 0000672A 83C40C add sp,12 ; clean up the stack again 0 0000672D 1F pop ds 0 0000672E 31C0 xor ax,ax 0 00006730 E8[0000] call return_AX_CLC 0 00006733 F8 clc 246 f7303_exit: 0 00006734 C3 ret 248 249 ; ************************************* 250 ; *** DOS Function 7305h *** 251 ; *** Extended Disk Read/write *** 252 ; ************************************* 253 ; 254 ;Entry: DL = drive number 255 ; DS:BX = pointer to disk address packet 256 ; CX = FFFFh 257 ; SI = read/write mode 258 ;Exit: CF clear 259 ;Error: CF set 260 ; AX = error code 261 262 func7305: 0 00006735 83F9FF cmp cx,0ffffh ; is CX=FFFFh given? 0 00006738 7405 je f7305_10 ; yes 0 0000673A B8A9FF mov ax, -57h ; if not, return 57h, RBIL calls it 266 ; "(DOS 3.3+) invalid parameter" 0 0000673D EB55 jmp f7305_exit ; no, then exit with error 268 f7305_10: 0 0000673F 06 push es 0 00006740 C42E[0000] les bp,[int21regs_ptr] ; ES:BX -> disk address structure 0 00006744 268B7608 mov si,[es:reg_SI + bp] 0 00006748 268B5E02 mov bx,[es:reg_BX + bp] 0 0000674C 268E460E mov es,[es:reg_DS + bp] 0 00006750 C706[0000]5400 mov word [FD_FUNC],FD_DDIO 0 00006756 FECA dec dl ; 0-based drive number 0 00006758 8816[0200] mov byte ptr [FD_DDIO_DRV_OP],dl 0 0000675C 268B07 mov ax,[es:bx] ; logical sector number 0 0000675F A3[0600] mov [FD_DDIO_STARTLOW],ax 0 00006762 268B4702 mov ax,[es:2 + bx] 0 00006766 A3[0800] mov [FD_DDIO_STARTHIGH],ax 0 00006769 268B4704 mov ax,[es:4 + bx] ; sectors to transfer 0 0000676D A3[0400] mov [FD_DDIO_NSECTORS],ax 0 00006770 268B4706 mov ax,[es:6 + bx] ; buffer address 0 00006774 A3[0A00] mov [FD_DDIO_DMAOFF],ax 0 00006777 268B4708 mov ax,[es:8 + bx] 0 0000677B A3[0C00] mov [FD_DDIO_DMASEG],ax 0 0000677E F7C60100 test si,1 ; test if read or write operation is requested 0 00006782 7507 jnz f7305_20 0 00006784 C606[0300]01 mov byte [FD_DDIO_DRV_OP+1],1 0 00006789 EB05 jmp f7305_30 291 f7305_20: 0 0000678B C606[0300]02 mov byte [FD_DDIO_DRV_OP+1],2 293 f7305_30: 0 00006790 07 pop es 0 00006791 E8[0000] call fdos_nocrit ; call fdos function 296 f7305_exit: 0 00006794 85C0 test ax, ax 0 00006796 7403 jz f7305_exit_NC 0 00006798 E9[0000] jmp error_exit 300 301 f7305_exit_NC: 0 0000679B E9[0000] jmp return_AX_CLC 303 304 PCM_CODE ends 305 === Switch to base=00C180h -> "PCMODE_DATA" 306 section PCMODE_DATA public align=2 class=DATA 307 308 extrn int21regs_ptr:dword 309 310 PCMODE_DATA ends 311 312 end === Trace listing source: drdos/bin/lfn.lst 1 ; LFN.ASM - Functions for Long Filename and 64-bit file size support 2 ; 3 ; This file is part of 4 ; The DR-DOS/OpenDOS Enhancement Project - http://www.drdosprojects.de 5 ; Copyright (c) 2002-2009 Udo Kuhnt 6 7 [list -] 16 17 group PCMCODE BDOS_CODE PCM_CODE 18 group PCMDATA BDOS_DATA PCMODE_DATA FDOS_DSEG 19 20 ASSUME DS:PCMDATA 21 === Switch to base=00C180h -> "BDOS_DATA" 22 section BDOS_DATA public align=2 class=DATA 23 extrn dcnt:word 24 extrn fdos_pb:word 25 26 extrn lfn_find_handles:word 27 extrn lfn_find_handles_end:word 28 extrn lfn_find_handle_heap:word 29 extrn lfn_find_handle_heap_end:word 30 extrn lfn_find_handle_heap_free:word 31 extrn lfnpathflag:byte 32 extrn lfn_search_redir:byte 33 BDOS_DATA ends 34 === Switch to base=00C180h -> "PCMODE_DATA" 35 section PCMODE_DATA public align=2 class=DATA 36 37 extrn int21regs_ptr:dword 38 extrn dma_segment:word 39 extrn dma_offset:word 40 extrn current_psp:word 41 PCMODE_DATA ends 42 === Switch to base=000000h -> "BDOS_CODE" 43 section BDOS_CODE public align=2 class=CODE 44 45 extrn rd_pcdir:near 46 extrn flush_dirbuf:near 47 48 ;Entry: DS:BX = pointer to dir entry 49 ; 50 ;Exit: carry flag set if LFN entry 51 Public is_lfn 52 is_lfn: 0 0000B826 807F0B0F cmp byte [DATTS + bx],DA_LFN ; attribute combination of LFN entry? 0 0000B82A 7508 jne is_lfn10 ; no, must be something else 0 0000B82C 837F1A00 cmp word ptr [BLOCK1 + bx],0 ; no cluster chain? 0 0000B830 7502 jne is_lfn10 ; perhaps it is a Delwatch entry 0 0000B832 F9 stc ; it is probably a Long Filename 0 0000B833 C3 ret 59 60 is_lfn10: 0 0000B834 F8 clc ; no LFN entry 0 0000B835 C3 ret 63 64 Public del_lfn 65 del_lfn: 0 0000B836 FF36[0000] push word [dcnt] ; save dir count 67 del_lfn10: 0 0000B83A 833E[0000]00 cmp word [dcnt],0 ; first entry in dir? 0 0000B83F 741A je del_lfn20 ; then no LFN can exist before it 0 0000B841 FF0E[0000] dec word [dcnt] ; point dir count to previous entry 0 0000B845 FF0E[0000] dec word [dcnt] 0 0000B849 E8[0000] call rd_pcdir ; read dir entry 0 0000B84C 89C3 mov bx,ax 0 0000B84E E8D5FF call is_lfn ; check if it is a long filename 0 0000B851 7308 jnc del_lfn20 ; no further LFN entries, done 0 0000B853 C607E5 mov byte [DNAME + bx],0e5h ; else mark this entry as deleted 0 0000B856 E8[0000] call flush_dirbuf ; and copy it to the buffer 0 0000B859 EBDF jmp del_lfn10 ; repeat with next entry 79 del_lfn20: 0 0000B85B 8F06[0000] pop word [dcnt] ; restore dir count 0 0000B85F FF0E[0000] dec word [dcnt] 0 0000B863 E8[0000] call rd_pcdir ; and old dir entry 0 0000B866 C3 ret 84 BDOS_CODE ends 85 === Switch to base=000000h -> "PCM_CODE" 86 section PCM_CODE public align=1 class=CODE 87 extrn return_AX_CLC:near 88 extrn vfy_dhndl_ptr_AX:near 89 extrn check_handle:near 90 extrn redir_dhndl_offer:near 91 extrn verify_handle:near 92 extrn mul32:near 93 extrn mul64:near 94 extrn dos_entry:near 95 extrn fdos_first:near 96 extrn fdos_next:near 97 extrn fdos_entry:near 98 extrn lds_si_dmaptr:near 99 extrn local_disk:near 100 extrn path_prep:near 101 extrn check_no_wild:near 102 extrn finddfcbf:near 103 extrn update_dir:near 104 105 Public func71 106 func71: 0 0000679E 3C42 cmp al,42h ; function 7142h? 0 000067A0 7430 je func7142 ; yes 0 000067A2 3C43 cmp al,43h ; function 7143h? 0 000067A4 7503 jne f71_4e 0 000067A6 E93201 jmp func7143 ; yes 112 f71_4e: 0 000067A9 3C4E cmp al,4eh ; function 714eh? 0 000067AB 7503 jne f71_4f 0 000067AD E99801 jmp func714e ; yes 116 f71_4f: 0 000067B0 3C4F cmp al,4fh ; function 714fh? 0 000067B2 7503 jne f71_a1 0 000067B4 E9DC01 jmp func714f ; yes 120 f71_a1: 0 000067B7 3CA1 cmp al,0a1h ; function 71a1h? 0 000067B9 7503 jne f71_a6 0 000067BB E99102 jmp func71a1 ; yes 124 f71_a6: 0 000067BE 3CA6 cmp al,0a6h ; function 71a6h? 0 000067C0 7503 jne func71_a7 0 000067C2 E9DF02 jmp func71a6 128 func71_a7: 0 000067C5 3CA7 cmp al,0a7h ; function 71a7h? 0 000067C7 7503 jne f71_error_7100 0 000067C9 E99703 jmp func71a7 ; yes 132 f71_error_7100: 0 000067CC B80071 mov ax,7100h ; function not supported 0 000067CF E96405 jmp f71_error 135 136 func7142: 0 000067D2 1E push ds 0 000067D3 C52E[0000] lds bp,[int21regs_ptr] 0 000067D7 3E8B4604 mov ax,[ds:reg_CX + bp] ; AL = original CL 0 000067DB 1F pop ds 0 000067DC 3C02 cmp al,2 ; valid subfunction number? 0 000067DE 7603 jbe f7142_02 0 000067E0 E95005 jmp f71_error_0001 144 f7142_02: 0 000067E3 89D8 mov ax,bx 0 000067E5 E84705 call vfy_dhndl_ptr_AX_call ; check file handle number 0 000067E8 7307 jnc f7142_handle_ok 0 000067EA 89D8 mov ax,bx 0 000067EC F7D8 neg ax 0 000067EE E94505 jmp f71_error 151 f7142_handle_ok: 0 000067F1 26F6470680 test byte ptr [es:DHNDL_WATTR+1 + bx],DHAT_REMOTE/100h 0 000067F6 742B jz f7142_not_redirector 154 155 f7142_redirector: 0 000067F8 89DF mov di, bx ; es:di -> SFT entry 157 0 000067FA 1E push ds 0 000067FB C52E[0000] lds bp,[int21regs_ptr] 0 000067FF 3E8B5606 mov dx,[ds:reg_DX + bp] 0 00006803 3E8E5E0E mov ds,[ds:reg_DS + bp]; ds:dx -> buffer 162 163 ; If either of the calls fails with error 1 164 ; it means that call is not supported. So we 165 ; try one, and if it returns error 1 then 166 ; either it meant to return the actual error 167 ; 1 or it isn't supported. Either way, we want 168 ; to try the other call then. 169 ; If 11C2h meant to return an actual error 1 170 ; then we'll still call 1142h, but either 171 ; 1142h isn't supported anymore (so we get the 172 ; eventual error 1 anyway), or it is also 173 ; supported and we will get the same error 1 174 ; again from the second call, too. 175 ; If 11C2h isn't supported we will call 1142h 176 ; and return whatever status it gives us. 0 00006807 B8C211 mov ax,11C2h 0 0000680A F9 stc 0 0000680B CD2F int 2Fh 0 0000680D 730B jnc f7142_ret_CF_ds ; supported and successful --> 0 0000680F 83F801 cmp ax,1 ; error 1 ? 0 00006812 F9 stc 0 00006813 7505 jne f7142_ret_CF_ds ; error other than 1, 184 ; that means it is supported. 185 ; return the other error --> 0 00006815 B84211 mov ax,1142h ; ax = 1142h 187 ; stc ; (already CY) 0 00006818 CD2F int 2Fh 189 f7142_ret_CF_ds: 0 0000681A 1F pop ds 191 f71_ret_CF: 0 0000681B 7203 jc f71_error_j 0 0000681D E9B400 jmp f7142_ret_success 194 195 f71_error_j: 0 00006820 E91305 jmp f71_error 197 198 f7142_not_redirector: 0 00006823 26F6470580 test byte [es:DHNDL_ATTR + bx],DHAT_DEV 0 00006828 7503 jnz f7142_dev ; skip a part if character device 201 f7142_05: 0 0000682A E8[0000] call check_handle ; check if valid file handle 203 f7142_dev: 0 0000682D 1E push ds 0 0000682E C52E[0000] lds bp,[int21regs_ptr] 0 00006832 3E8B4604 mov ax,[ds:reg_CX + bp] ; AL = original CL 0 00006836 3E8B7606 mov si,[ds:reg_DX + bp] ; DS:SI -> QWORD for position offset and result 0 0000683A 3E8E5E0E mov ds,[ds:reg_DS + bp] 0 0000683E 08C0 or al,al 0 00006840 7406 je f7142_10 ; seek from beginning 0 00006842 FEC8 dec al 0 00006844 741F je f7142_20 ; seek from current position 0 00006846 EB55 jmp f7142_30 ; seek from end 214 215 f7142_10: ; mode 0: set absolute position 0 00006848 8B04 mov ax,[si] ; copy 64-bit offset to position 0 0000684A 26894715 mov [es:DHNDL_POSLO + bx],ax 0 0000684E 8B4402 mov ax,[2 + si] 0 00006851 26894717 mov [es:DHNDL_POSHI + bx],ax 0 00006855 8B4404 mov ax,[4 + si] 0 00006858 26894747 mov [es:DHNDL_POSXLO + bx],ax 0 0000685C 8B4406 mov ax,[6 + si] 0 0000685F 26894749 mov [es:DHNDL_POSXHI + bx],ax 0 00006863 EB6E jmp f7142_40 225 226 f7142_20: ; mode 1: relative to current position 0 00006865 8B04 mov ax,[si] ; add 64-bit offset to position 0 00006867 26034715 add ax,[es:DHNDL_POSLO + bx] 0 0000686B 26894715 mov [es:DHNDL_POSLO + bx],ax 0 0000686F 8904 mov [si],ax ; and store new position as result 0 00006871 8B4402 mov ax,[2 + si] 0 00006874 26134717 adc ax,[es:DHNDL_POSHI + bx] 0 00006878 26894717 mov [es:DHNDL_POSHI + bx],ax 0 0000687C 894402 mov [2 + si],ax 0 0000687F 8B4404 mov ax,[4 + si] 0 00006882 26134747 adc ax,[es:DHNDL_POSXLO + bx] 0 00006886 26894747 mov [es:DHNDL_POSXLO + bx],ax 0 0000688A 894404 mov [4 + si],ax 0 0000688D 8B4406 mov ax,[6 + si] 0 00006890 26134749 adc ax,[es:DHNDL_POSXHI + bx] 0 00006894 26894749 mov [es:DHNDL_POSXHI + bx],ax 0 00006898 894406 mov [6 + si],ax 0 0000689B EB36 jmp f7142_40 244 245 f7142_30: ; mode 2: relative to end of file 0 0000689D 8B04 mov ax,[si] ; add 64-bit offset to file size 0 0000689F 26034711 add ax,[es:DHNDL_SIZELO + bx] 0 000068A3 26894715 mov [es:DHNDL_POSLO + bx],ax ; and store as new position 0 000068A7 8904 mov [si],ax ; and result 0 000068A9 8B4402 mov ax,[2 + si] 0 000068AC 26134713 adc ax,[es:DHNDL_SIZEHI + bx] 0 000068B0 26894717 mov [es:DHNDL_POSHI + bx],ax 0 000068B4 894402 mov [2 + si],ax 0 000068B7 8B4404 mov ax,[4 + si] 0 000068BA 26134743 adc ax,[es:DHNDL_SIZEXLO + bx] 0 000068BE 26894747 mov [es:DHNDL_POSXLO + bx],ax 0 000068C2 894404 mov [4 + si],ax 0 000068C5 8B4406 mov ax,[6 + si] 0 000068C8 26134745 adc ax,[es:DHNDL_SIZEXHI + bx] 0 000068CC 26894749 mov [es:DHNDL_POSXHI + bx],ax 0 000068D0 894406 mov [6 + si],ax 262 f7142_40: 0 000068D3 1F pop ds 264 f7142_ret_success: 0 000068D4 31C0 xor ax,ax 0 000068D6 E8[0000] call return_AX_CLC 0 000068D9 F8 clc 0 000068DA C3 ret 269 270 func7143: 0 000068DB 80FB03 cmp bl,3 ; check subfunction range 0 000068DE 7408 je f7143_10 0 000068E0 80FB04 cmp bl,4 0 000068E3 7403 je f7143_10 0 000068E5 E9E4FE jmp f71_error_7100 276 f7143_10: 0 000068E8 A3[0000] mov [FD_FUNC],ax ; function number 0 000068EB 8916[0200] mov [FD_NAMEOFF],dx ; filename 0 000068EF 8C06[0400] mov [FD_NAMESEG],es 0 000068F3 BA[0000] mov dx,offset fdos_data ; parameter block 0 000068F6 1E push ds ; set up FDOS stack frame 0 000068F7 52 push dx 0 000068F8 50 push ax 0 000068F9 50 push ax 0 000068FA E8[0000] call local_disk ; make local copy of parameters 0 000068FD E8[0000] call path_prep ; parse path 0 00006900 E8[0000] call check_no_wild ; wildcards not allowed 0 00006903 7506 jnz f7143_20 0 00006905 B80200 mov ax,2 ; file not found 0 00006908 E92B04 jmp f71_error 291 f7143_20: 0 0000690B E8[0000] call finddfcbf ; locate dir entry 0 0000690E 7506 jnz f7143_30 0 00006910 B80200 mov ax,2 ; file not found 0 00006913 E92004 jmp f71_error 296 f7143_30: 0 00006916 C42E[0000] les bp,[int21regs_ptr] 0 0000691A 268B4602 mov ax,[es:reg_BX + bp] 0 0000691E 3C03 cmp al,3 ; subfunction 3? 0 00006920 7410 je f7143_set_writetime 301 f7143_get_writetime: 0 00006922 8B4F16 mov cx,[DTIME + bx] ; last write time 0 00006925 8B7F18 mov di,[DDATE + bx] ; last write date 0 00006928 26894E04 mov [es:reg_CX + bp],cx 0 0000692C 26897E0A mov [es:reg_DI + bp],di 0 00006930 EB11 jmp f7143_exit 307 f7143_set_writetime: 0 00006932 268B4E04 mov cx,[es:reg_CX + bp] ; new last write time 0 00006936 268B7E0A mov di,[es:reg_DI + bp] ; new last write date 0 0000693A 894F16 mov [DTIME + bx],cx 0 0000693D 897F18 mov [DDATE + bx],di 0 00006940 E8[0000] call update_dir ; update dir entry 313 f7143_exit: 0 00006943 31C0 xor ax,ax ; no error 0 00006945 E9[0000] jmp return_AX_CLC 316 317 func714e: 0 00006948 30ED xor ch,ch 0 0000694A 890E[0800] mov [FD_ATTRIB],cx ; search attributes 0 0000694E 8916[0200] mov [FD_NAMEOFF],dx ; search pattern 0 00006952 8C06[0400] mov [FD_NAMESEG],es 322 323 ; We don't need to store the pathname, 324 ; the DTA will have everything needed. 325 %if 0 326 mov di, dx 327 mov cx, -1 328 mov al, 0 329 repne scasb 330 not cx ; cx = size 331 add cx, 2 + 1 332 and cl, 0FEh 333 %endif 334 0 00006956 1E push ds 0 00006957 07 pop es 0 00006958 BF[0000] mov di, offset lfn_find_handles 0 0000695B 31C0 xor ax, ax 339 f714e_loop_handle: 0 0000695D AF scasw 0 0000695E 740C je f714e_found_handle 0 00006960 81FF[0000] cmp di, offset lfn_find_handles_end 0 00006964 72F7 jb f714e_loop_handle 344 345 f714e_oom: 0 00006966 B80400 mov ax, 4 ; "too many open handles" 0 00006969 E9CA03 jmp f71_error 348 349 f714e_found_handle: 0 0000696C B92E00 mov cx, 2Eh ; size needed 351 0 0000696F B8[0000] mov ax, offset lfn_find_handle_heap_end 0 00006972 8B1E[0000] mov bx, [lfn_find_handle_heap_free] 0 00006976 29D8 sub ax, bx 0 00006978 39C8 cmp ax, cx 0 0000697A 72EA jb f714e_oom 357 0 0000697C 895DFE mov word ptr [di-2], bx 0 0000697F 010E[0000] add [lfn_find_handle_heap_free], cx 0 00006983 A1[0000] mov ax, [current_psp] 0 00006986 8907 mov word ptr [bx], ax 0 00006988 81EF[0200] sub di, offset lfn_find_handles + 2 0 0000698C D1EF shr di, 1 ; make it a handle 364 0 0000698E B84E00 mov ax,4eh ; FindFirst 0 00006991 EB0B jmp f714e_entry 367 368 func714f: 0 00006993 E8F200 call lfn_get_handle 0 00006996 72CE jc f714e_oom 371 0 00006998 B44F mov ah, 4Fh 0 0000699A 97 xchg di, ax ; al = from handle, ah = 4Fh 374 0 0000699B B84F00 mov ax,4fh ; FindNext 376 f714e_entry: 0 0000699E 43 inc bx 0 0000699F 43 inc bx ; -> our DTA 0 000069A0 A3[0000] mov [FD_FUNC],ax 380 ; mov FD_LFNSEARCH,1 ; use FAT+/LFN extensions 0 000069A3 C706[0A00]0100 mov word [fdos_pb+10],1 ; use FAT+/LFN extensions 0 000069A9 C706[0000]0100 mov word [lfnpathflag], 1 ; lfn_search_redir = 0 0 000069AF 57 push di ; handle 0 000069B0 1E push ds 0 000069B1 36FF36[0000] push word [ss:dma_segment] ; save old DTA 0 000069B6 36FF36[0000] push word [ss:dma_offset] 0 000069BB 368C1E[0000] mov [ss:dma_segment],ds 0 000069C0 36891E[0000] mov [ss:dma_offset],bx 0 000069C5 BA[0000] mov dx,offset fdos_data 0 000069C8 E8[0000] call fdos_entry ; call FindNext function 0 000069CB 83F8A6 cmp ax,ED_LASTERROR ; has an error occurred? 0 000069CE 7222 jb f714f_10 ; no 0 000069D0 368F06[0000] pop word [ss:dma_offset] ; restore old DTA 0 000069D5 368F06[0000] pop word [ss:dma_segment] 0 000069DA 1F pop ds 0 000069DB 5B pop bx ; = handle for 714Eh 397 0 000069DC 50 push ax 0 000069DD 833E[0000]4E cmp word [FD_FUNC], 4Eh ; was find first ? 0 000069E2 7508 jne f714e_error_findnext ; no --> 401 0 000069E4 E8A100 call lfn_get_handle ; get handle data 0 000069E7 7203 jc f714e_error_findnext ; (cannot happen) 0 000069E9 E87300 call lfn_free_handle ; free handle, as we cannot return it 405 406 f714e_error_findnext: 0 000069EC 58 pop ax 0 000069ED F7D8 neg ax 0 000069EF E94403 jmp f71_error 410 f714f_10: 0 000069F2 C42E[0000] les bp,[int21regs_ptr] ; ES:BP -> initial parameters 0 000069F6 268B7E0A mov di,[es:reg_DI + bp] 0 000069FA 26FF7610 push word [es:reg_ES + bp] 0 000069FE 07 pop es ; ES:DI -> Find Data buffer 0 000069FF E8[0000] call lds_si_dmaptr ; DS:SI -> DTA 0 00006A02 83C615 add si,15h ; start at file attribute field 0 00006A05 AC lodsb ; file attribute 0 00006A06 30E4 xor ah,ah 0 00006A08 AB stosw 0 00006A09 31C0 xor ax,ax ; set additional file times to 0 0 00006A0B AB stosw 0 00006A0C AB stosw 0 00006A0D AB stosw 0 00006A0E AB stosw 0 00006A0F AB stosw 0 00006A10 AB stosw 0 00006A11 AB stosw 0 00006A12 AB stosw 0 00006A13 AB stosw 0 00006A14 A5 movsw ; file time 0 00006A15 A5 movsw ; file date 0 00006A16 31C0 xor ax,ax ; zero high dword 0 00006A18 AB stosw 0 00006A19 AB stosw 0 00006A1A 36D006[0000] rol byte [ss:lfn_search_redir], 1 0 00006A1F 7203 jc f714F_redir_no_plus_size 0 00006A21 8A44F9 mov al,[si-7] ; extended file size 438 f714F_redir_no_plus_size: 0 00006A24 AB stosw 0 00006A25 31C0 xor ax,ax 0 00006A27 AB stosw 0 00006A28 A5 movsw ; file size low 0 00006A29 A5 movsw 0 00006A2A 83C708 add di,8 ; skip over reserved bytes 0 00006A2D B90D00 mov cx,13 0 00006A30 F3A4 rep movsb ; copy file name 0 00006A32 81C7F700 add di,260 - 13 ; start of short name field 0 00006A36 AA stosb ; no short name (0) 0 00006A37 368F06[0000] pop word [ss:dma_offset] ; restore old DTA 0 00006A3C 368F06[0000] pop word [ss:dma_segment] 0 00006A41 1F pop ds 0 00006A42 C42E[0000] les bp,[int21regs_ptr] 0 00006A46 26894604 mov [es:reg_CX + bp],ax ; Unicode conversion flags (0) 0 00006A4A 58 pop ax ; return handle 0 00006A4B E8[0000] call return_AX_CLC ; no error 0 00006A4E C3 ret 457 458 func71a1: 0 00006A4F E83600 call lfn_get_handle 0 00006A52 7208 jc f714e_oom_j 0 00006A54 E80800 call lfn_free_handle 0 00006A57 31C0 xor ax, ax 0 00006A59 E9[0000] jmp return_AX_CLC 464 465 f714e_oom_j: 0 00006A5C E907FF jmp f714e_oom 467 468 469 Public lfn_free_handle 470 471 lfn_free_handle: 0 00006A5F 89D8 mov ax, bx 0 00006A61 832500 and word ptr [di], 0 ; clear the handle table 0 00006A64 1E push ds 0 00006A65 07 pop es 0 00006A66 89C7 mov di, ax ; -> to overwrite 0 00006A68 8D752E lea si, [di+2Eh] ; -> next 0 00006A6B B9[0000] mov cx, offset lfn_find_handle_heap_end 479 ; -> after last 0 00006A6E 29F1 sub cx, si ; = length of next to after last 0 00006A70 F3A4 rep movsb ; move down 0 00006A72 BF[0000] mov di, offset lfn_find_handles 483 f71a1_loop: 0 00006A75 AF scasw ; cmp ax, word ptr [es:di] 0 00006A76 7704 ja f71a1_next ; offset freed is above entry --> 0 00006A78 836DFE2E sub word ptr [di-2], 2Eh ; offset freed is below, relocate this 487 f71a1_next: 0 00006A7C 81FF[0000] cmp di, offset lfn_find_handles_end 489 ; more to go ? 0 00006A80 72F3 jb f71a1_loop ; yes --> 0 00006A82 832E[0000]2E sub word [lfn_find_handle_heap_free], 2Eh 492 lfn_free_handle_ret: 0 00006A87 C3 ret 494 495 496 ; INP: bx = handle 497 ; OUT: NC if valid handle, 498 ; ax = original handle 499 ; bx -> DTA 500 ; di -> handle table entry 501 ; CY if no valid handle 502 lfn_get_handle: 0 00006A88 89D8 mov ax, bx 0 00006A8A 01DB add bx, bx ; get handle 0 00006A8C 7214 jc lfn_get_handle_ret_CY 0 00006A8E 81C3[0000] add bx, offset lfn_find_handles 0 00006A92 720E jc lfn_get_handle_ret_CY 0 00006A94 81FB[0000] cmp bx, offset lfn_find_handles_end 0 00006A98 7308 jae lfn_get_handle_ret_CY 0 00006A9A 89DF mov di, bx 0 00006A9C 8B1F mov bx, word ptr [bx] ; = offset of our DTA (0 = invalid) 0 00006A9E 85DB test bx, bx 0 00006AA0 7501 jnz lfn_get_handle_ret ; valid --> (NC) 514 lfn_get_handle_ret_CY: 0 00006AA2 F9 stc 516 lfn_get_handle_ret: 0 00006AA3 C3 ret 518 519 520 func71a6: 0 00006AA4 89D8 mov ax,bx 0 00006AA6 E88602 call vfy_dhndl_ptr_AX_call ; check file handle number 0 00006AA9 7307 jnc f71a6_handle_ok 0 00006AAB 89D8 mov ax,bx 0 00006AAD F7D8 neg ax 0 00006AAF E98402 jmp f71_error 527 f71a6_handle_ok: 0 00006AB2 26F6470680 test byte ptr [es:DHNDL_WATTR+1 + bx],DHAT_REMOTE/100h 0 00006AB7 7426 jz f71a6_not_redirector 530 531 f71a6_redirector: 0 00006AB9 89DF mov di, bx ; es:di -> SFT entry 533 0 00006ABB 1E push ds 0 00006ABC C52E[0000] lds bp,[int21regs_ptr] 0 00006AC0 3E8B5606 mov dx,[ds:reg_DX + bp] 0 00006AC4 3E8E5E0E mov ds,[ds:reg_DS + bp]; ds:dx -> buffer 538 0 00006AC8 B8A611 mov ax,11A6h 0 00006ACB F9 stc 0 00006ACC CD2F int 2Fh ; dosemu2 extension function 0 00006ACE 7309 jnc f71a6_ret_CF_ds ; supported and successful --> 0 00006AD0 83F801 cmp ax,1 ; error 1 ? 0 00006AD3 F9 stc ; indicate error (CY) 0 00006AD4 7503 jne f71a6_ret_CF_ds 0 00006AD6 B80071 mov ax, 7100h ; MSWindows 4 returns CY, ax=7100h on redirector 547 ; (still CY) 548 549 f71a6_ret_CF_ds: 0 00006AD9 E93EFD jmp f7142_ret_CF_ds 551 552 f71a6_dev: 0 00006ADC E9EDFC jmp f71_error_7100 554 555 f71a6_not_redirector: 0 00006ADF 26F6470580 test byte [es:DHNDL_ATTR + bx],DHAT_DEV 0 00006AE4 75F6 jnz f71a6_dev ; skip if character device 0 00006AE6 E8[0000] call verify_handle ; check if valid file handle 0 00006AE9 1E push ds 0 00006AEA C52E[0000] lds bp,[int21regs_ptr] ; DS:DI -> buffer for Get File Info structure 0 00006AEE 3E8B7E06 mov di,[ds:reg_DX + bp] 0 00006AF2 3E8E5E0E mov ds,[ds:reg_DS + bp] 0 00006AF6 1E push ds ; ES:DI -> buffer, DS:BX -> DHNDL 0 00006AF7 06 push es 0 00006AF8 1F pop ds 0 00006AF9 07 pop es 0 00006AFA 30E4 xor ah,ah 0 00006AFC 8A4705 mov al,[DHNDL_ATTR + bx] ; file attributes 0 00006AFF AB stosw 0 00006B00 31C0 xor ax,ax 0 00006B02 AB stosw 0 00006B03 B90800 mov cx,8 0 00006B06 F3AB rep stosw ; creation time (0 = unsupported) 574 ; last access time (0 = unsupported) 0 00006B08 53 push bx 0 00006B09 8B570F mov dx,[DHNDL_DATE + bx] ; last write time 0 00006B0C 8B4F0D mov cx,[DHNDL_TIME + bx] 0 00006B0F 31DB xor bx,bx ; 0 milliseconds 0 00006B11 E86D00 call f71a701_entry2 0 00006B14 5B pop bx 0 00006B15 83C708 add di,8 0 00006B18 1E push ds ; save DS 0 00006B19 89E5 mov bp,sp ; restore PCM DS 0 00006B1B 8E5E02 mov ds,[2 + bp] 0 00006B1E 83EC19 sub sp,25 ; reserve space on stack 0 00006B21 89E5 mov bp,sp 0 00006B23 06 push es ; save registers 0 00006B24 53 push bx 0 00006B25 57 push di 0 00006B26 8CD0 mov ax,ss ; ES:DX -> buffer for media info 0 00006B28 8EC0 mov es,ax 0 00006B2A 89EA mov dx,bp 0 00006B2C 31DB xor bx,bx ; current drive 0 00006B2E B80069 mov ax,6900h ; Get Volume Serial Number 0 00006B31 E8[0000] call dos_entry 0 00006B34 5F pop di ; restore registers 0 00006B35 5B pop bx 0 00006B36 07 pop es 0 00006B37 8B4602 mov ax,[2 + bp] ; volume serial number 0 00006B3A AB stosw 0 00006B3B 8B4604 mov ax,[4 + bp] 0 00006B3E AB stosw 0 00006B3F 83C419 add sp,25 ; clean up stack again 0 00006B42 1F pop ds ; restore DS 0 00006B43 8B4743 mov ax,[DHNDL_SIZEXLO + bx] ; file size high 0 00006B46 AB stosw 0 00006B47 8B4745 mov ax,[DHNDL_SIZEXHI + bx] 0 00006B4A AB stosw 0 00006B4B 8B4711 mov ax,[DHNDL_SIZELO + bx] ; file size low 0 00006B4E AB stosw 0 00006B4F 8B4713 mov ax,[DHNDL_SIZEHI + bx] 0 00006B52 AB stosw 0 00006B53 31C0 xor ax,ax 0 00006B55 40 inc ax ; links to file (1) 0 00006B56 AB stosw 0 00006B57 48 dec ax 0 00006B58 AB stosw 0 00006B59 AB stosw ; file identifier 0 00006B5A AB stosw 0 00006B5B AB stosw 0 00006B5C AB stosw 0 00006B5D 1F pop ds 0 00006B5E E8[0000] call return_AX_CLC 0 00006B61 F8 clc 0 00006B62 C3 ret 626 627 func71a7: 0 00006B63 80FB01 cmp bl,01 ; sub function 01? 0 00006B66 7403 je f71a701 ; yes 0 00006B68 E961FC jmp f71_error_7100 631 f71a701: ; Convert DOS time to Windows time 0 00006B6B E80700 call f71a701_entry 0 00006B6E 31C0 xor ax,ax 0 00006B70 E8[0000] call return_AX_CLC 0 00006B73 F8 clc 0 00006B74 C3 ret 637 638 f71a701_entry: 0 00006B75 C42E[0000] les bp,[int21regs_ptr] ; ES:DI -> 64-bit time 640 REG_DI equ reg_DI ; NASM port equate 0 00006B79 268B7E0A mov di,[es:REG_DI + bp] 642 REG_ES equ reg_ES ; NASM port equate 0 00006B7D 268E4610 mov es,[es:REG_ES + bp] 644 f71a701_entry2: 0 00006B81 89E5 mov bp,sp 0 00006B83 52 push dx ; save date 0 00006B84 51 push cx ; save time 0 00006B85 86DF xchg bl,bh 0 00006B87 30FF xor bh,bh 0 00006B89 53 push bx 0 00006B8A 83FA00 cmp dx,0 ; special case - date and time zero 0 00006B8D 7513 jnz f71a701_05 0 00006B8F 83F900 cmp cx,0 0 00006B92 750E jnz f71a701_05 0 00006B94 31C0 xor ax,ax ; clear buffer 0 00006B96 FC cld 0 00006B97 B90400 mov cx,4 0 00006B9A F3AB rep stosw 0 00006B9C 83EF08 sub di,8 0 00006B9F E92001 jmp f71a701_80 661 f71a701_05: 0 00006BA2 89D0 mov ax,dx 0 00006BA4 2500FE and ax,0fe00h ; bits 9-15 contain the year - 1980 0 00006BA7 B109 mov cl,9 0 00006BA9 D3E8 shr ax,cl 0 00006BAB 057B01 add ax,379 ; AX = year - 1601 0 00006BAE 50 push ax 0 00006BAF B96D01 mov cx,365 0 00006BB2 F7E1 mul cx ; convert to days (without leap days) 0 00006BB4 268905 mov [es:di],ax ; save to ES:DI 0 00006BB7 26895502 mov [es:2 + di],dx 0 00006BBB 58 pop ax 0 00006BBC 31DB xor bx,bx ; compute leap days in 400 years 0 00006BBE 31D2 xor dx,dx 0 00006BC0 B99001 mov cx,400 0 00006BC3 F7F1 div cx 0 00006BC5 3C00 cmp al,0 ; at least 400 years? 0 00006BC7 7402 jz f71a701_10 ; no 0 00006BC9 B361 mov bl,97 ; 97 leap days 680 f71a701_10: 0 00006BCB 89D0 mov ax,dx ; divide remainder by 100 0 00006BCD B164 mov cl,100 ; to compute leap days in 100 years 0 00006BCF F6F1 div cl 0 00006BD1 3C03 cmp al,3 0 00006BD3 7502 jne f71a701_20 0 00006BD5 B504 mov ch,4 687 f71a701_20: 0 00006BD7 50 push ax 0 00006BD8 B118 mov cl,24 ; 24 leap days 0 00006BDA F6E1 mul cl 0 00006BDC 00C3 add bl,al 0 00006BDE 58 pop ax 0 00006BDF 86E0 xchg ah,al 0 00006BE1 30E4 xor ah,ah ; divide remainder by 4 0 00006BE3 B104 mov cl,4 ; to compute remaining leap days 0 00006BE5 F6F1 div cl 0 00006BE7 3C18 cmp al,24 0 00006BE9 7503 jne f71a701_30 0 00006BEB 80CD02 or ch,2 700 f71a701_30: 0 00006BEE 00C3 add bl,al ; remaining leap days in century 0 00006BF0 80FC03 cmp ah,3 0 00006BF3 7503 jne f71a701_40 0 00006BF5 80CD01 or ch,1 705 f71a701_40: 0 00006BF8 31C0 xor ax,ax ; add leap days 0 00006BFA 88D8 mov al,bl 0 00006BFC 260105 add [es:di],ax 0 00006BFF 2683550200 adc word ptr [es:2 + di],0 0 00006C04 8B46FE mov ax,[bp-2] ; restore date 0 00006C07 25E001 and ax,1e0h ; bits 5-8 contain the month 0 00006C0A B105 mov cl,5 0 00006C0C D3E8 shr ax,cl 0 00006C0E 89C3 mov bx,ax 0 00006C10 31F6 xor si,si 0 00006C12 46 inc si 0 00006C13 31D2 xor dx,dx 0 00006C15 31C0 xor ax,ax 719 f71a701_50: 0 00006C17 39DE cmp si,bx 0 00006C19 740A je f71a701_60 0 00006C1B 2E8A94[8505] mov dl,[cs:ndays + si] 0 00006C20 01D0 add ax,dx 0 00006C22 46 inc si 0 00006C23 EBF2 jmp f71a701_50 726 f71a701_60: 0 00006C25 83FB02 cmp bx,2 ; has February already passed? 0 00006C28 770B ja f71a701_70 ; no 0 00006C2A F6C501 test ch,1 ; is the year a leap year? 0 00006C2D 7406 jz f71a701_70 ; no 0 00006C2F 80FD03 cmp ch,3 ; 100/400-years rule 0 00006C32 7401 je f71a701_70 ; 100 but not 400, no leap year 0 00006C34 40 inc ax ; yes, add one leap day 734 f71a701_70: 0 00006C35 8B56FE mov dx,[bp-2] ; restore date 0 00006C38 83E21F and dx,1fh ; bits 0-4 contain the days 0 00006C3B 01D0 add ax,dx ; AX = days in year 0 00006C3D 48 dec ax ; minus one for the first day in 1601 0 00006C3E 260105 add [es:di],ax ; date converted to days 0 00006C41 2683550200 adc word ptr [es:2 + di],0 741 0 00006C46 26FF7502 push word ptr [es:2 + di] ; number of days 0 00006C4A 26FF35 push word ptr [es:di] 0 00006C4D 31C0 xor ax,ax 0 00006C4F 50 push ax 0 00006C50 B8C0A8 mov ax,43200 ; 2-seconds per day 0 00006C53 50 push ax 0 00006C54 83EC08 sub sp,8 ; reserve space on stack 0 00006C57 E8[0000] call mul32 ; convert to 2-seconds 0 00006C5A 268F05 pop word ptr [es:di] ; save subtotal 0 00006C5D 268F4502 pop word ptr [es:2 + di] 0 00006C61 268F4504 pop word ptr [es:4 + di] 0 00006C65 268F4506 pop word ptr [es:6 + di] 0 00006C69 83C408 add sp,8 ; clean up stack again 0 00006C6C 8B46FC mov ax,[bp-4] ; restore time 0 00006C6F 2500F8 and ax,0f800h ; bits 11-15 contain the hours 0 00006C72 B10B mov cl,11 0 00006C74 D3E8 shr ax,cl 0 00006C76 B90807 mov cx,1800 0 00006C79 F7E1 mul cx ; convert to 2-seconds 0 00006C7B 260105 add [es:di],ax ; and add subtotal 0 00006C7E 26115502 adc [es:2 + di],dx 0 00006C82 2683550400 adc word ptr [es:4 + di],0 0 00006C87 2683550600 adc word ptr [es:6 + di],0 0 00006C8C 8B46FC mov ax,[bp-4] ; restore time 0 00006C8F 25E007 and ax,7e0h ; bits 5-10 contain the minutes 0 00006C92 B105 mov cl,5 0 00006C94 D3E8 shr ax,cl 0 00006C96 B11E mov cl,30 0 00006C98 F6E1 mul cl ; convert to 2-seconds 0 00006C9A 260105 add [es:di],ax ; and add subtotal 0 00006C9D 26115502 adc [es:2 + di],dx 0 00006CA1 2683550400 adc word ptr [es:4 + di],0 0 00006CA6 2683550600 adc word ptr [es:6 + di],0 0 00006CAB 8B46FC mov ax,[bp-4] ; restore time 0 00006CAE 83E01F and ax,1fh ; bits 0-4 contain the 2-seconds 0 00006CB1 260105 add [es:di],ax ; and add subtotal 0 00006CB4 26115502 adc [es:2 + di],dx 0 00006CB8 2683550400 adc word ptr [es:4 + di],0 0 00006CBD 2683550600 adc word ptr [es:6 + di],0 781 f71a701_80: 0 00006CC2 26FF7506 push word ptr [es:6 + di] ; number of 2-seconds 0 00006CC6 26FF7504 push word ptr [es:4 + di] 0 00006CCA 26FF7502 push word ptr [es:2 + di] 0 00006CCE 26FF35 push word ptr [es:di] 0 00006CD1 31C0 xor ax,ax 0 00006CD3 50 push ax 0 00006CD4 50 push ax 0 00006CD5 B83101 mov ax,131h ; 1312d00h = 20000000 100-nanoseconds 0 00006CD8 50 push ax 0 00006CD9 B8002D mov ax,2d00h 0 00006CDC 50 push ax 0 00006CDD 83EC10 sub sp,16 ; reserve space on stack 0 00006CE0 E8[0000] call mul64 ; convert to 100-nanoseconds 0 00006CE3 268F05 pop word ptr [es:di] ; save subtotal 0 00006CE6 268F4502 pop word ptr [es:2 + di] 0 00006CEA 268F4504 pop word ptr [es:4 + di] 0 00006CEE 268F4506 pop word ptr [es:6 + di] 0 00006CF2 83C418 add sp,24 ; clean up stack again 0 00006CF5 31C0 xor ax,ax ; centiseconds 0 00006CF7 50 push ax 0 00006CF8 FF76FA push word ptr [bp-6] 0 00006CFB B80100 mov ax,1 ; 186A0h = 100000 100-nanoseconds 0 00006CFE 50 push ax 0 00006CFF B8A086 mov ax,86a0h 0 00006D02 50 push ax 0 00006D03 83EC08 sub sp,8 ; reserve space on stack 0 00006D06 E8[0000] call mul32 0 00006D09 58 pop ax 0 00006D0A 5A pop dx 0 00006D0B 83C40C add sp,12 ; clean up stack again 0 00006D0E 260105 add [es:di],ax ; and add to result 0 00006D11 26115502 adc [es:2 + di],dx 0 00006D15 2683550400 adc word ptr [es:4 + di],0 0 00006D1A 2683550600 adc word ptr [es:6 + di],0 0 00006D1F 83C406 add sp,6 0 00006D22 C3 ret 818 0 00006D23 1F1C1F1E1F1E1F1F1E ndays db 31,28,31,30,31,30,31,31,30,31,30,31 0 00006D2C 1F1E1F 820 821 vfy_dhndl_ptr_AX_call: 0 00006D2F E8[0000] call vfy_dhndl_ptr_AX ; setup stack for vfy_dhndl_ptr_AX 0 00006D32 C3 ret 824 825 f71_error_0001: 0 00006D33 B80100 mov ax,1 ; invalid function number 827 828 f71_error: 0 00006D36 C42E[0000] les bp,[int21regs_ptr] 0 00006D3A 26894600 mov [es:reg_AX + bp],ax ; return error code 0 00006D3E 26834E1601 or word [es:reg_FLAGS + bp],CARRY_FLAG ; set carry flag 0 00006D43 F9 stc 0 00006D44 C3 ret 834 PCM_CODE ends 835 836 end