diff options
| author | 2024-04-25 21:24:10 +0100 | |
|---|---|---|
| committer | 2024-04-25 22:32:27 +0000 | |
| commit | 2d04cacc5322951f187bb17e017c12920ac8ebe2 (patch) | |
| tree | 80ee017efa878dfd5344b44249e6a241f2a7f6e2 /v4.0/src/DOS/FCBIO.ASM | |
| parent | Merge pull request #430 from jpbaltazar/typoptbr (diff) | |
| download | ms-dos-main.tar.gz ms-dos-main.tar.xz ms-dos-main.zip | |
Diffstat (limited to 'v4.0/src/DOS/FCBIO.ASM')
| -rw-r--r-- | v4.0/src/DOS/FCBIO.ASM | 1185 |
1 files changed, 1185 insertions, 0 deletions
diff --git a/v4.0/src/DOS/FCBIO.ASM b/v4.0/src/DOS/FCBIO.ASM new file mode 100644 index 0000000..8b27d72 --- /dev/null +++ b/v4.0/src/DOS/FCBIO.ASM | |||
| @@ -0,0 +1,1185 @@ | |||
| 1 | ; SCCSID = @(#)fcbio.asm 1.5 85/07/30 | ||
| 2 | ; SCCSID = @(#)fcbio.asm 1.5 85/07/30 | ||
| 3 | TITLE FCBIO - FCB system calls | ||
| 4 | NAME FCBIO | ||
| 5 | |||
| 6 | ; | ||
| 7 | ; Ancient 1.0 1.1 FCB system calls | ||
| 8 | ; regen save | ||
| 9 | ; $GET_FCB_POSITION written none none | ||
| 10 | ; $FCB_DELETE written none none | ||
| 11 | ; $GET_FCB_FILE_LENGTH written none none | ||
| 12 | ; $FCB_CLOSE written close none | ||
| 13 | ; $FCB_RENAME written none none | ||
| 14 | ; SaveFCBInfo | ||
| 15 | ; ResetLRU | ||
| 16 | ; SetOpenAge | ||
| 17 | ; LRUFCB | ||
| 18 | ; FCBRegen | ||
| 19 | ; BlastSFT | ||
| 20 | ; CheckFCB | ||
| 21 | ; SFTFromFCB | ||
| 22 | ; FCBHardErr | ||
| 23 | ; | ||
| 24 | ; Revision history: | ||
| 25 | ; | ||
| 26 | ; Created: ARR 4 April 1983 | ||
| 27 | ; MZ 6 June 1983 completion of functions | ||
| 28 | ; MZ 15 Dec 1983 Brain damaged programs close FCBs multiple | ||
| 29 | ; times. Change so successive closes work by | ||
| 30 | ; always returning OK. Also, detect I/O to | ||
| 31 | ; already closed FCB and return EOF. | ||
| 32 | ; MZ 16 Jan 1984 More braindamage. Need to separate info | ||
| 33 | ; out of sft into FCB for reconnection | ||
| 34 | ; | ||
| 35 | ; A000 version 4.00 Jan. 1988 | ||
| 36 | ; | ||
| 37 | .xlist | ||
| 38 | ; | ||
| 39 | ; get the appropriate segment definitions | ||
| 40 | ; | ||
| 41 | include dosseg.asm | ||
| 42 | |||
| 43 | CODE SEGMENT BYTE PUBLIC 'CODE' | ||
| 44 | ASSUME SS:DOSGROUP,CS:DOSGROUP | ||
| 45 | |||
| 46 | .xcref | ||
| 47 | INCLUDE DOSSYM.INC | ||
| 48 | INCLUDE DEVSYM.INC | ||
| 49 | INCLUDE FASTOPEN.INC | ||
| 50 | .cref | ||
| 51 | .list | ||
| 52 | |||
| 53 | AsmVars <Kanji> | ||
| 54 | |||
| 55 | I_need OpenBuf,128 ; buffer for translating paths | ||
| 56 | I_need RenBuf,128 ; buffer for rename paths | ||
| 57 | i_need THISDPB,DWORD | ||
| 58 | i_need EXTERR,WORD | ||
| 59 | i_need ALLOWED,BYTE | ||
| 60 | I_need ThisSFT,DWORD ; SFT in use | ||
| 61 | I_need WFP_start,WORD ; pointer to canonical name | ||
| 62 | I_need Ren_WFP,WORD ; pointer to canonical name | ||
| 63 | I_need Attrib,BYTE ; Attribute for match attributes | ||
| 64 | I_need sftFCB,DWORD ; pointer to SFTs for FCB cache | ||
| 65 | I_need FCBLRU,WORD ; least recently used count | ||
| 66 | I_need Proc_ID,WORD ; current process ID | ||
| 67 | I_Need Name1,14 ; place for device names | ||
| 68 | I_need DEVPT,DWORD ; device pointer | ||
| 69 | I_need OpenLRU,WORD ; open age | ||
| 70 | I_need KeepCount,WORD ; number of fcbs to keep | ||
| 71 | I_need User_In_AX,WORD ; user input system call. | ||
| 72 | I_need JShare,DWORD ; share jump table | ||
| 73 | I_need FastOpenTable,BYTE ; DOS 3.3 fastopen | ||
| 74 | if debug | ||
| 75 | I_need BugLev,WORD | ||
| 76 | I_need BugTyp,WORD | ||
| 77 | include bugtyp.asm | ||
| 78 | endif | ||
| 79 | |||
| 80 | |||
| 81 | Break <$Get_FCB_Position - set random record fields to current pos> | ||
| 82 | |||
| 83 | ; | ||
| 84 | ; $Get_FCB_Position - look at an FCB, retrieve the current position from the | ||
| 85 | ; extent and next record field and set the random record field to point | ||
| 86 | ; to that record | ||
| 87 | ; | ||
| 88 | ; Inputs: DS:DX point to a possible extended FCB | ||
| 89 | ; Outputs: The random record field of the FCB is set to the current record | ||
| 90 | ; Registers modified: all | ||
| 91 | |||
| 92 | Procedure $Get_FCB_Position,NEAR | ||
| 93 | ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup | ||
| 94 | invoke GetExtended ; point to FCB | ||
| 95 | invoke GetExtent ; DX:AX is current record | ||
| 96 | MOV WORD PTR [SI.fcb_RR],AX ; drop in low order piece | ||
| 97 | MOV [SI+fcb_RR+2],DL ; drop in high order piece | ||
| 98 | CMP [SI.fcb_RECSIZ],64 | ||
| 99 | JAE GetFCBBye | ||
| 100 | MOV [SI+fcb_RR+2+1],DH ; Set 4th byte only if record size < 64 | ||
| 101 | GetFCBBye: | ||
| 102 | transfer FCB_Ret_OK | ||
| 103 | EndProc $GET_FCB_POSITION | ||
| 104 | |||
| 105 | Break <$FCB_Delete - remove several files that match the input FCB> | ||
| 106 | |||
| 107 | ; | ||
| 108 | ; $FCB_delete - given an FCB, remove all directory entries in the current | ||
| 109 | ; directory that have names that match the FCB's ? marks. | ||
| 110 | ; | ||
| 111 | ; Inputs: DS:DX - point to an FCB | ||
| 112 | ; Outputs: directory entries matching the FCB are deleted | ||
| 113 | ; AL = FF if no entries were deleted. | ||
| 114 | ; Registers modified: all | ||
| 115 | |||
| 116 | Procedure $FCB_Delete,NEAR | ||
| 117 | ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup | ||
| 118 | MOV DI,OFFSET DOSGroup:OpenBuf ; appropriate place | ||
| 119 | invoke TransFCB ; convert FCB to path | ||
| 120 | JC BadPath ; signal no deletions | ||
| 121 | Context DS | ||
| 122 | invoke DOS_Delete ; wham | ||
| 123 | JC BadPath | ||
| 124 | GoodPath: | ||
| 125 | transfer FCB_Ret_OK ; do a good return | ||
| 126 | BadPath: | ||
| 127 | ; | ||
| 128 | |||
| 129 | ; Error code is in AX | ||
| 130 | ; | ||
| 131 | transfer FCB_Ret_Err ; let someone else signal the error | ||
| 132 | EndProc $FCB_DELETE | ||
| 133 | |||
| 134 | Break <$Get_FCB_File_Length - return the length of a file> | ||
| 135 | |||
| 136 | ; | ||
| 137 | ; $Get_FCB_File_Length - set the random record field to the length of the | ||
| 138 | ; file in records (rounded up if partial). | ||
| 139 | ; | ||
| 140 | ; Inputs: DS:DX - point to a possible extended FCB | ||
| 141 | ; Outputs: Random record field updated to reflect the number of records | ||
| 142 | ; Registers modified: all | ||
| 143 | |||
| 144 | Procedure $Get_FCB_File_Length,NEAR | ||
| 145 | ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup | ||
| 146 | invoke GetExtended ; get real FCB pointer | ||
| 147 | ; DX points to Input FCB | ||
| 148 | MOV DI,OFFSET DOSGroup:OpenBuf ; appropriate buffer | ||
| 149 | SaveReg <DS,SI> ; save pointer to true FCB | ||
| 150 | Invoke TransFCB ; Trans name DS:DX, sets SATTRIB | ||
| 151 | RestoreReg <SI,DS> | ||
| 152 | JC BadPath | ||
| 153 | SaveReg <DS,SI> ; save pointer | ||
| 154 | Context DS | ||
| 155 | invoke Get_File_Info ; grab the info | ||
| 156 | RestoreReg <SI,DS> ; get pointer back | ||
| 157 | JC BadPath ; invalid something | ||
| 158 | MOV DX,BX ; get high order size | ||
| 159 | MOV AX,DI ; get low order size | ||
| 160 | MOV BX,[SI.fcb_RECSIZ] ; get his record size | ||
| 161 | OR BX,BX ; empty record => 0 size for file | ||
| 162 | JNZ GetSize ; not empty | ||
| 163 | MOV BX,128 | ||
| 164 | GetSize: | ||
| 165 | MOV DI,AX ; save low order word | ||
| 166 | MOV AX,DX ; move high order for divide | ||
| 167 | XOR DX,DX ; clear out high | ||
| 168 | DIV BX ; wham | ||
| 169 | PUSH AX ; save dividend | ||
| 170 | MOV AX,DI ; get low order piece | ||
| 171 | DIV BX ; wham | ||
| 172 | MOV CX,DX ; save remainder | ||
| 173 | POP DX ; get high order dividend | ||
| 174 | JCXZ LengthStore ; no roundup | ||
| 175 | ADD AX,1 | ||
| 176 | ADC DX,0 ; 32-bit increment | ||
| 177 | LengthStore: | ||
| 178 | MOV WORD PTR [SI.FCB_RR],AX ; store low order | ||
| 179 | MOV [SI.FCB_RR+2],DL ; store high order | ||
| 180 | OR DH,DH | ||
| 181 | JZ GoodPath ; not storing insignificant zero | ||
| 182 | MOV [SI.FCB_RR+3],DH ; save that high piece | ||
| 183 | GoodRet: | ||
| 184 | transfer FCB_Ret_OK | ||
| 185 | EndProc $GET_FCB_FILE_LENGTH | ||
| 186 | |||
| 187 | Break <$FCB_Close - close a file> | ||
| 188 | |||
| 189 | ; | ||
| 190 | ; $FCB_Close - given an FCB, look up the SFN and close it. Do not free it | ||
| 191 | ; as the FCB may be used for further I/O | ||
| 192 | ; | ||
| 193 | ; Inputs: DS:DX point to FCB | ||
| 194 | ; Outputs: AL = FF if file was not found on disk | ||
| 195 | ; Registers modified: all | ||
| 196 | |||
| 197 | Procedure $FCB_Close,NEAR | ||
| 198 | ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup | ||
| 199 | XOR AL,AL ; default search attributes | ||
| 200 | invoke GetExtended ; DS:SI point to real FCB | ||
| 201 | JZ NoAttr ; not extended | ||
| 202 | MOV AL,[SI-1] ; get attributes | ||
| 203 | NoAttr: | ||
| 204 | MOV [Attrib],AL ; stash away found attributes | ||
| 205 | invoke SFTFromFCB | ||
| 206 | JC GoodRet ; MZ 16 Jan Assume death | ||
| 207 | ; | ||
| 208 | ; If the sharer is present, then the SFT is not regenable. Thus, there is | ||
| 209 | ; no need to set the SFT's attribute. | ||
| 210 | ; | ||
| 211 | ;;; 9/8/86 F.C. save SFT attribute and restore it back when close is done | ||
| 212 | MOV AL,ES:[DI].sf_attr | ||
| 213 | XOR AH,AH | ||
| 214 | PUSH AX | ||
| 215 | ;;; 9/8/86 F.C. save SFT attribute and restore it back when close is done | ||
| 216 | invoke CheckShare | ||
| 217 | JNZ NoStash | ||
| 218 | MOV AL,Attrib | ||
| 219 | MOV ES:[DI].sf_attr,AL ; attempted attribute for close | ||
| 220 | NoStash: | ||
| 221 | MOV AX,[SI].FCB_FDATE ; move in the time and date | ||
| 222 | MOV ES:[DI].sf_date,AX | ||
| 223 | MOV AX,[SI].FCB_FTIME | ||
| 224 | MOV ES:[DI].sf_time,AX | ||
| 225 | MOV AX,[SI].FCB_FilSiz | ||
| 226 | MOV WORD PTR ES:[DI].sf_size,AX | ||
| 227 | MOV AX,[SI].FCB_FilSiz+2 | ||
| 228 | MOV WORD PTR ES:[DI].sf_size+2,AX | ||
| 229 | OR ES:[DI].sf_Flags,sf_close_nodate | ||
| 230 | Context DS ; let Close see variables | ||
| 231 | invoke DOS_Close ; wham | ||
| 232 | LES DI,ThisSFT | ||
| 233 | ;;; 9/8/86 F.C. restore SFT attribute | ||
| 234 | POP CX | ||
| 235 | MOV ES:[DI].sf_attr,CL | ||
| 236 | ;;; 9/8/86 F.C. restore SFT attribute | ||
| 237 | PUSHF | ||
| 238 | TEST ES:[DI.sf_ref_count],-1 ; zero ref count gets blasted | ||
| 239 | JNZ CloseOK | ||
| 240 | PUSH AX | ||
| 241 | MOV AL,'M' | ||
| 242 | invoke BlastSFT | ||
| 243 | POP AX | ||
| 244 | CloseOK: | ||
| 245 | POPF | ||
| 246 | JNC GoodRet | ||
| 247 | CMP AL,error_invalid_handle | ||
| 248 | JZ GoodRet | ||
| 249 | MOV AL,error_file_not_found | ||
| 250 | transfer FCB_Ret_Err | ||
| 251 | EndProc $FCB_CLOSE | ||
| 252 | |||
| 253 | Break <$FCB_Rename - change names in place> | ||
| 254 | |||
| 255 | ; | ||
| 256 | ; $FCB_Rename - rename a file in place within a directory. Renames multiple | ||
| 257 | ; files copying from the meta characters. | ||
| 258 | ; | ||
| 259 | ; Inputs: DS:DX point to an FCB. The normal name field is the source | ||
| 260 | ; name of the files to be renamed. Starting at offset 11h | ||
| 261 | ; in the FCB is the destination name. | ||
| 262 | ; Outputs: AL = 0 -> no error occurred and all files were renamed | ||
| 263 | ; AL = FF -> some files may have been renamed but: | ||
| 264 | ; rename to existing file or source file not found | ||
| 265 | ; Registers modified: all | ||
| 266 | |||
| 267 | Procedure $FCB_Rename,NEAR | ||
| 268 | ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:DOSGroup | ||
| 269 | invoke GetExtended ; get pointer to real FCB | ||
| 270 | SaveReg <DX> | ||
| 271 | MOV AL,[SI] ; get drive byte | ||
| 272 | ADD SI,10h ; point to destination | ||
| 273 | MOV DI,OFFSET DOSGroup:RenBuf ; point to destination buffer | ||
| 274 | SaveReg <<WORD PTR DS:[SI]>,DS,SI> ; save source pointer for TransFCB | ||
| 275 | MOV DS:[SI],AL ; drop in real drive | ||
| 276 | MOV DX,SI ; let TransFCB know where the FCB is | ||
| 277 | invoke TransFCB ; munch this pathname | ||
| 278 | RestoreReg <SI,DS,<WORD PTR DS:[SI]>> ; get path back | ||
| 279 | RestoreReg <DX> ; Original FCB pointer | ||
| 280 | JC BadRen ; bad path -> error | ||
| 281 | MOV SI,WFP_Start ; get pointer | ||
| 282 | MOV Ren_WFP,SI ; stash it | ||
| 283 | MOV DI,OFFSET DOSGroup:OpenBuf ; appropriate spot | ||
| 284 | invoke TransFCB ; wham | ||
| 285 | ; NOTE that this call is pointing | ||
| 286 | ; back to the ORIGINAL FCB so | ||
| 287 | ; SATTRIB gets set correctly | ||
| 288 | JC BadRen ; error | ||
| 289 | invoke DOS_Rename | ||
| 290 | JC BadRen | ||
| 291 | transfer FCB_Ret_OK | ||
| 292 | BadRen: | ||
| 293 | ; | ||
| 294 | ; AL has error code | ||
| 295 | ; | ||
| 296 | transfer FCB_Ret_Err | ||
| 297 | |||
| 298 | EndProc $FCB_RENAME | ||
| 299 | |||
| 300 | Break <Misbehavior fixers> | ||
| 301 | |||
| 302 | ; | ||
| 303 | ; FCBs suffer from several problems. First, they are maintained in the | ||
| 304 | ; user's space so he may move them at will. Second, they have a small | ||
| 305 | ; reserved area that may be used for system information. Third, there was | ||
| 306 | ; never any "rules for behavior" for FCBs; there was no protocol for their | ||
| 307 | ; usage. | ||
| 308 | ; | ||
| 309 | ; This results in the following misbehavior: | ||
| 310 | ; | ||
| 311 | ; infinite opens of the same file: | ||
| 312 | ; | ||
| 313 | ; While (TRUE) { While (TRUE) { | ||
| 314 | ; FCBOpen (FCB); FCBOpen (FCB); | ||
| 315 | ; Read (FCB); Write (FCB); | ||
| 316 | ; } } | ||
| 317 | ; | ||
| 318 | ; infinite opens of different files: | ||
| 319 | ; | ||
| 320 | ; While (TRUE) { While (TRUE) { | ||
| 321 | ; FCBOpen (FCB[i++]); FCBOpen (FCB[i++]); | ||
| 322 | ; Read (FCB); Write (FCB); | ||
| 323 | ; } } | ||
| 324 | ; | ||
| 325 | ; multiple closes of the same file: | ||
| 326 | ; | ||
| 327 | ; FCBOpen (FCB); | ||
| 328 | ; while (TRUE) | ||
| 329 | ; FCBClose (FCB); | ||
| 330 | ; | ||
| 331 | ; I/O after closing file: | ||
| 332 | ; | ||
| 333 | ; FCBOpen (FCB); | ||
| 334 | ; while (TRUE) { | ||
| 335 | ; FCBWrite (FCB); | ||
| 336 | ; FCBClose (FCB); | ||
| 337 | ; } | ||
| 338 | ; | ||
| 339 | ; The following is am implementation of a methodology for emulating the | ||
| 340 | ; above with the exception of I/O after close. We are NOT attempting to | ||
| 341 | ; resolve that particular misbehavior. We will enforce correct behaviour in | ||
| 342 | ; FCBs when they refer to a network file or when there is file sharing on | ||
| 343 | ; the local machine. | ||
| 344 | ; | ||
| 345 | ; The reserved fields of the FCB (10 bytes worth) is divided up into various | ||
| 346 | ; structures depending on the file itself and the state of operations of the | ||
| 347 | ; OS. The information contained in this reserved field is enough to | ||
| 348 | ; regenerate the SFT for the local non-shared file. It is assumed that this | ||
| 349 | ; regeneration procedure may be expensive. The SFT for the FCB is | ||
| 350 | ; maintained in a LRU cache as the ONLY performance inprovement. | ||
| 351 | ; | ||
| 352 | ; No regeneration of SFTs is attempted for network FCBs. | ||
| 353 | ; | ||
| 354 | ; To regenerate the SFT for a local FCB, it is necessary to determine if the | ||
| 355 | ; file sharer is working. If the file sharer is present then the SFT is not | ||
| 356 | ; regenerated. | ||
| 357 | ; | ||
| 358 | ; Finally, if there is no local sharing, the full name of the file is no | ||
| 359 | ; longer available. We can make up for this by using the following | ||
| 360 | ; information: | ||
| 361 | ; | ||
| 362 | ; The Drive number (from the DPB). | ||
| 363 | ; The physical sector of the directory that contains the entry. | ||
| 364 | ; The relative position of the entry in the sector. | ||
| 365 | ; The first cluster field. | ||
| 366 | ; The last used SFT. | ||
| 367 | ; OR In the case of a device FCB | ||
| 368 | ; The low 6 bits of sf_flags (indicating device type) | ||
| 369 | ; The pointer to the device header | ||
| 370 | ; | ||
| 371 | ; | ||
| 372 | ; We read in the particular directory sector and examine the indicated | ||
| 373 | ; directory entry. If it matches, then we are kosher; otherwise, we fail. | ||
| 374 | ; | ||
| 375 | ; Some key items need to be remembered: | ||
| 376 | ; | ||
| 377 | ; Even though we are caching SFTs, they may contain useful sharing | ||
| 378 | ; information. We enforce good behavior on the FCBs. | ||
| 379 | ; | ||
| 380 | ; Network support must not treat FCBs as impacting the ref counts on | ||
| 381 | ; open VCs. The VCs may be closed only at process termination. | ||
| 382 | ; | ||
| 383 | ; If this is not an installed version of the DOS, file sharing will | ||
| 384 | ; always be present. | ||
| 385 | ; | ||
| 386 | ; We MUST always initialize lstclus to = firclus when regenerating a | ||
| 387 | ; file. Otherwise we start allocating clusters up the wazoo. | ||
| 388 | ; | ||
| 389 | ; Always initialize, during regeneration, the mode field to both isFCB | ||
| 390 | ; and open_for_both. This is so the FCB code in the sharer can find the | ||
| 391 | ; proper OI record. | ||
| 392 | ; | ||
| 393 | ; The test bits are: | ||
| 394 | ; | ||
| 395 | ; 00 -> local file | ||
| 396 | ; 40 -> sharing local | ||
| 397 | ; 80 -> network | ||
| 398 | ; C0 -> local device | ||
| 399 | |||
| 400 | Break <SaveFCBInfo - store pertinent information from an SFT into the FCB> | ||
| 401 | |||
| 402 | ; | ||
| 403 | ; SaveFCBInfo - given an FCB and its associated SFT, copy the relevant | ||
| 404 | ; pieces of information into the FCB to allow for subsequent | ||
| 405 | ; regeneration. Poke LRU also. | ||
| 406 | ; | ||
| 407 | ; Inputs: ThisSFT points to a complete SFT. | ||
| 408 | ; DS:SI point to the FCB (not an extended one) | ||
| 409 | ; Outputs: The relevant reserved fields in the FCB are filled in. | ||
| 410 | ; DS:SI preserved | ||
| 411 | ; ES:DI point to sft | ||
| 412 | ; Registers modified: All | ||
| 413 | ; | ||
| 414 | |||
| 415 | Procedure SaveFCBInfo,NEAR | ||
| 416 | ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup | ||
| 417 | LES DI,ThisSFT | ||
| 418 | Assert ISSFT,<ES,DI>,"SaveFCBInfo" | ||
| 419 | invoke IsSFTNet | ||
| 420 | JZ SaveLocal ; if not network then save local info | ||
| 421 | ; | ||
| 422 | ;----- In net support ----- | ||
| 423 | ; | ||
| 424 | MOV AX,WORD PTR ES:[DI].sf_serial_ID ;AN000;;IFS. save IFS ID | ||
| 425 | MOV WORD PTR [SI].FCB_netID,ax ;AN000;;IFS. | ||
| 426 | ; SaveReg <ES,DI> | ||
| 427 | ; LES DI,DWORD PTR ES:[DI].sf_netid | ||
| 428 | ; MOV WORD PTR [SI].FCB_netID,DI ; save net ID | ||
| 429 | ; MOV WORD PTR [SI].FCB_netID+2,ES | ||
| 430 | ; RestoreReg <DI,ES> | ||
| 431 | MOV BL,FCBNETWORK | ||
| 432 | ; | ||
| 433 | ;----- END In net support ----- | ||
| 434 | ; | ||
| 435 | IF debug | ||
| 436 | JMP SaveSFN | ||
| 437 | ELSE | ||
| 438 | JMP SHORT SaveSFN | ||
| 439 | ENDIF | ||
| 440 | SaveLocal: | ||
| 441 | IF Installed | ||
| 442 | Invoke CheckShare | ||
| 443 | JZ SaveNoShare ; no sharer | ||
| 444 | JMP SaveShare ; sharer present | ||
| 445 | |||
| 446 | SaveNoShare: | ||
| 447 | TEST ES:[DI].sf_flags,devid_device | ||
| 448 | JNZ SaveNoShareDev ; Device | ||
| 449 | ; | ||
| 450 | ; Save no sharing local file information | ||
| 451 | ; | ||
| 452 | MOV AX,WORD PTR ES:[DI].sf_dirsec ; get directory sector F.C. | ||
| 453 | MOV [SI].fcb_nsl_dirsec,AX | ||
| 454 | MOV AL,ES:[DI].sf_dirpos ; location in sector | ||
| 455 | MOV [SI].fcb_nsl_dirpos,AL | ||
| 456 | MOV AX,ES:[DI].sf_firclus ; first cluster | ||
| 457 | MOV [SI].fcb_nsl_firclus,AX | ||
| 458 | MOV BL,00 | ||
| 459 | ; | ||
| 460 | ; Create the bits field from the dirty/device bits of the flags word and the | ||
| 461 | ; mode byte | ||
| 462 | ; | ||
| 463 | SetFCBBits: | ||
| 464 | MOV AX,ES:[DI].sf_flags | ||
| 465 | AND AL,0C0h ; mask off drive bits | ||
| 466 | OR AL,BYTE PTR ES:[DI].sf_mode ; stick in open mode | ||
| 467 | MOV [SI].fcb_nsl_bits,AL ; save dirty info | ||
| 468 | JMP SaveSFN ; go and save SFN | ||
| 469 | |||
| 470 | ; | ||
| 471 | ; Save no sharing local device information | ||
| 472 | ; | ||
| 473 | SaveNoShareDev: | ||
| 474 | MOV AX,WORD PTR ES:[DI].sf_devptr | ||
| 475 | MOV WORD PTR [SI].FCB_nsld_drvptr,AX | ||
| 476 | MOV AX,WORD PTR ES:[DI].sf_devptr + 2 | ||
| 477 | MOV WORD PTR [SI].FCB_nsld_drvptr + 2,AX | ||
| 478 | MOV BL,FCBDEVICE | ||
| 479 | JMP SetFCBBits ; go and save SFN | ||
| 480 | |||
| 481 | SaveShare: | ||
| 482 | ENDIF | ||
| 483 | ; | ||
| 484 | ;----- In share support ----- | ||
| 485 | ; | ||
| 486 | if installed | ||
| 487 | Call JShare + 10 * 4 | ||
| 488 | else | ||
| 489 | Call ShSave | ||
| 490 | endif | ||
| 491 | ; | ||
| 492 | ;----- end in share support ----- | ||
| 493 | ; | ||
| 494 | SaveSFN: | ||
| 495 | MOV AX,ES:[DI].sf_flags | ||
| 496 | AND AL,3Fh ; get real drive | ||
| 497 | OR AL,BL | ||
| 498 | MOV [SI].fcb_l_drive,AL | ||
| 499 | LEA AX,[DI-SFTable] | ||
| 500 | ; | ||
| 501 | ; Adjust for offset to table. | ||
| 502 | ; | ||
| 503 | SUB AX,WORD PTR SftFCB | ||
| 504 | MOV BL,SIZE sf_entry | ||
| 505 | DIV BL | ||
| 506 | MOV [SI].FCB_sfn,AL ; last used SFN | ||
| 507 | MOV AX,FCBLRU ; get lru count | ||
| 508 | INC AX | ||
| 509 | MOV WORD PTR ES:[DI].sf_LRU,AX | ||
| 510 | JNZ SimpleStuff | ||
| 511 | ; | ||
| 512 | ; lru flag overflowed. Run through all FCB sfts and adjust: LRU < 8000h | ||
| 513 | ; get set to 0. Others -= 8000h. This LRU = 8000h | ||
| 514 | ; | ||
| 515 | MOV BX,sf_position | ||
| 516 | invoke ResetLRU | ||
| 517 | ; | ||
| 518 | ; Set new LRU to AX | ||
| 519 | ; | ||
| 520 | SimpleStuff: | ||
| 521 | MOV FCBLRU,AX | ||
| 522 | return | ||
| 523 | EndProc SaveFCBInfo | ||
| 524 | |||
| 525 | Break <ResetLRU - reset overflowed lru counts> | ||
| 526 | |||
| 527 | ; | ||
| 528 | ; ResetLRU - during lru updates, we may wrap at 64K. We must walk the | ||
| 529 | ; entire set of SFTs and subtract 8000h from their lru counts and truncate | ||
| 530 | ; at 0. | ||
| 531 | ; | ||
| 532 | ; Inputs: BX is offset into SFT field where lru firld is kept | ||
| 533 | ; ES:DI point to SFT currently being updated | ||
| 534 | ; Outputs: All FCB SFTs have their lru fields truncated | ||
| 535 | ; AX has 8000h | ||
| 536 | ; Registers modified: none | ||
| 537 | |||
| 538 | Procedure ResetLRU,NEAR | ||
| 539 | ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING | ||
| 540 | Assert ISSFT,<ES,DI>,"ResetLRU" | ||
| 541 | MOV AX,8000h | ||
| 542 | SaveReg <ES,DI> | ||
| 543 | LES DI,sftFCB ; get pointer to head | ||
| 544 | MOV CX,ES:[DI].sfCount | ||
| 545 | LEA DI,[DI].sfTable ; point at table | ||
| 546 | ovScan: | ||
| 547 | SUB WORD PTR ES:[DI+BX],AX ; decrement lru count | ||
| 548 | JA ovLoop | ||
| 549 | MOV WORD PTR ES:[DI.BX],AX ; truncate at 0 | ||
| 550 | ovLoop: | ||
| 551 | ADD DI,SIZE SF_Entry ; advance to next | ||
| 552 | LOOP ovScan | ||
| 553 | RestoreReg <DI,ES> | ||
| 554 | MOV ES:[DI+BX],AX | ||
| 555 | return | ||
| 556 | EndProc ResetLRU | ||
| 557 | |||
| 558 | Break <SetOpenAge - update the open age of a SFT> | ||
| 559 | |||
| 560 | ; | ||
| 561 | ; SetOpenAge - In order to maintain the first N open files in the FCB cache, | ||
| 562 | ; we keep the 'open age' or an LRU count based on opens. We update the | ||
| 563 | ; count here and fill in the appropriate field. | ||
| 564 | ; | ||
| 565 | ; Inputs: ES:DI point to SFT | ||
| 566 | ; Outputs: ES:DI has the open age field filled in. | ||
| 567 | ; If open age has wraparound, we will have subtracted 8000h | ||
| 568 | ; from all open ages. | ||
| 569 | ; Registers modified: AX | ||
| 570 | ; | ||
| 571 | |||
| 572 | Procedure SetOpenAge,NEAR | ||
| 573 | ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING | ||
| 574 | Assert ISSFT,<ES,DI>,"SetOpenAge" | ||
| 575 | MOV AX,OpenLRU | ||
| 576 | INC AX | ||
| 577 | MOV ES:[DI].sf_OpenAge,AX | ||
| 578 | JNZ SetDone | ||
| 579 | MOV BX,sf_Position+2 | ||
| 580 | invoke ResetLRU | ||
| 581 | SetDone: | ||
| 582 | MOV OpenLRU,AX | ||
| 583 | return | ||
| 584 | EndProc SetOpenAge | ||
| 585 | |||
| 586 | Break <LRUFCB - perform LRU on FCB sfts> | ||
| 587 | |||
| 588 | ; | ||
| 589 | ; LRUFCB - find LRU fcb in cache. Set ThisSFT and return it. We preserve | ||
| 590 | ; the first keepcount sfts if they are network sfts or if sharing is | ||
| 591 | ; loaded. If carry is set then NO BLASTING is NECESSARY. | ||
| 592 | ; | ||
| 593 | ; Inputs: none | ||
| 594 | ; Outputs: ES:DI point to SFT | ||
| 595 | ; ThisSFT points to SFT | ||
| 596 | ; SFT is zeroed | ||
| 597 | ; Carry set of closes failed | ||
| 598 | ; Registers modified: none | ||
| 599 | ; | ||
| 600 | |||
| 601 | Procedure LRUFCB,NEAR | ||
| 602 | ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING | ||
| 603 | Invoke Save_World | ||
| 604 | ; | ||
| 605 | ; Find nth oldest NET/SHARE FCB. We want to find its age for the second scan | ||
| 606 | ; to find the lease recently used one that is younger than the open age. We | ||
| 607 | ; operate be scanning the list n times finding the least age that is greater | ||
| 608 | ; or equal to the previous minimum age. | ||
| 609 | ; | ||
| 610 | ; BP is the count of times we need to go through this loop. | ||
| 611 | ; AX is the current acceptable minimum age to consider | ||
| 612 | ; | ||
| 613 | mov bp,KeepCount ; k = keepcount; | ||
| 614 | XOR AX,AX ; low = 0; | ||
| 615 | ; | ||
| 616 | ; If we've scanned the table n times, then we are done. | ||
| 617 | ; | ||
| 618 | lru1: | ||
| 619 | CMP bp,0 ; while (k--) { | ||
| 620 | JZ lru75 | ||
| 621 | DEC bp | ||
| 622 | ; | ||
| 623 | ; Set up for scan. | ||
| 624 | ; | ||
| 625 | ; AX is the minimum age for consideration | ||
| 626 | ; BX is the minimum age found during the scan | ||
| 627 | ; SI is the position of the entry that corresponds to BX | ||
| 628 | ; | ||
| 629 | MOV BX,-1 ; min = 0xffff; | ||
| 630 | MOV si,BX ; pos = 0xffff; | ||
| 631 | LES DI,SFTFCB ; for (CX=FCBCount; CX>0; CX--) | ||
| 632 | MOV CX,ES:[DI].sfCount | ||
| 633 | LEA DI,[DI].sfTable | ||
| 634 | ; | ||
| 635 | ; Innermost loop. If the current entry is free, then we are done. Or, if the | ||
| 636 | ; current entry is busy (indicating a previous aborted allocation), then we | ||
| 637 | ; are done. In both cases, we use the found entry. | ||
| 638 | ; | ||
| 639 | lru2: | ||
| 640 | cmp es:[di].sf_ref_count,0 | ||
| 641 | jz lru25 | ||
| 642 | cmp es:[di].sf_ref_count,sf_busy | ||
| 643 | jnz lru3 | ||
| 644 | ; | ||
| 645 | ; The entry is usable without further scan. Go and use it. | ||
| 646 | ; | ||
| 647 | lru25: | ||
| 648 | MOV si,DI ; pos = i; | ||
| 649 | JMP lru11 ; goto got; | ||
| 650 | ; | ||
| 651 | ; See if the entry is for the network or for the sharer. | ||
| 652 | ; | ||
| 653 | ; If for the sharer or network then | ||
| 654 | ; if the age < current minimum AND >= allowed minimum then | ||
| 655 | ; this entry becomes current minimum | ||
| 656 | ; | ||
| 657 | lru3: | ||
| 658 | TEST ES:[DI].sf_flags,sf_isnet ; if (!net[i] | ||
| 659 | JNZ lru35 | ||
| 660 | if installed | ||
| 661 | Invoke CheckShare ; && !sharing) | ||
| 662 | JZ lru5 ; else | ||
| 663 | ENDIF | ||
| 664 | ; | ||
| 665 | ; This SFT is for the net or is for the sharer. See if it less than the | ||
| 666 | ; current minimum. | ||
| 667 | ; | ||
| 668 | lru35: | ||
| 669 | MOV DX,ES:[DI].sf_OpenAge | ||
| 670 | CMP DX,AX ; if (age[i] >= low && | ||
| 671 | JB lru5 | ||
| 672 | CMP DX,BX | ||
| 673 | JAE lru5 ; age[i] < min) { | ||
| 674 | ; | ||
| 675 | ; entry is new minimum. Remember his age. | ||
| 676 | ; | ||
| 677 | mov bx,DX ; min = age[i]; | ||
| 678 | mov si,di ; pos = i; | ||
| 679 | ; | ||
| 680 | ; End of loop. gp back for more | ||
| 681 | ; | ||
| 682 | lru5: | ||
| 683 | add di,size sf_entry | ||
| 684 | loop lru2 ; } | ||
| 685 | ; | ||
| 686 | ; The scan is complete. If we have successfully found a new minimum (pos != -1) | ||
| 687 | ; set then threshold value to this new minimum + 1. Otherwise, the scan is | ||
| 688 | ; complete. Go find LRU. | ||
| 689 | ; | ||
| 690 | lru6: cmp si,-1 ; position not -1? | ||
| 691 | jz lru75 ; no, done with everything | ||
| 692 | lea ax,[bx+1] ; set new threshold age | ||
| 693 | jmp lru1 ; go and loop for more | ||
| 694 | lru65: stc | ||
| 695 | jmp short lruDead ; return -1; | ||
| 696 | ; | ||
| 697 | ; Main loop is done. We have AX being the age+1 of the nth oldest sharer or | ||
| 698 | ; network entry. We now make a second pass through to find the LRU entry | ||
| 699 | ; that is local-no-share or has age >= AX | ||
| 700 | ; | ||
| 701 | lru75: | ||
| 702 | mov bx,-1 ; min = 0xffff; | ||
| 703 | mov si,bx ; pos = 0xffff; | ||
| 704 | LES DI,SFTFCB ; for (CX=FCBCount; CX>0; CX--) | ||
| 705 | MOV CX,ES:[DI].sfCount | ||
| 706 | LEA DI,[DI].sfTable | ||
| 707 | ; | ||
| 708 | ; If this is is local-no-share then go check for LRU else if age >= threshold | ||
| 709 | ; then check for lru. | ||
| 710 | ; | ||
| 711 | lru8: | ||
| 712 | TEST ES:[DI].sf_flags,sf_isnet | ||
| 713 | jnz lru85 ; is for network, go check age | ||
| 714 | invoke CheckShare ; sharer here? | ||
| 715 | jz lru86 ; no, go check lru | ||
| 716 | ; | ||
| 717 | ; Network or sharer. Check age | ||
| 718 | ; | ||
| 719 | lru85: | ||
| 720 | cmp es:[di].sf_OpenAge,ax | ||
| 721 | jb lru9 ; age is before threshold, skip it | ||
| 722 | ; | ||
| 723 | ; Check LRU | ||
| 724 | ; | ||
| 725 | lru86: | ||
| 726 | cmp es:[di].sf_LRU,bx ; is LRU less than current LRU? | ||
| 727 | jae lru9 ; no, skip this | ||
| 728 | mov si,di ; remember position | ||
| 729 | mov bx,es:[di].sf_LRU ; remember new minimum LRU | ||
| 730 | ; | ||
| 731 | ; Done with this entry, go back for more. | ||
| 732 | ; | ||
| 733 | lru9: | ||
| 734 | add di,size sf_entry | ||
| 735 | loop lru8 | ||
| 736 | ; | ||
| 737 | ; Scan is complete. If we found NOTHING that satisfied us then we bomb | ||
| 738 | ; out. The conditions here are: | ||
| 739 | ; | ||
| 740 | ; No local-no-shares AND all net/share entries are older than threshold | ||
| 741 | ; | ||
| 742 | lru10: | ||
| 743 | cmp si,-1 ; if no one f | ||
| 744 | jz lru65 ; return -1; | ||
| 745 | lru11: | ||
| 746 | mov di,si | ||
| 747 | MOV WORD PTR ThisSFT,DI ; set thissft | ||
| 748 | MOV WORD PTR ThisSFT+2,ES | ||
| 749 | ; | ||
| 750 | ; If we have sharing or thisSFT is a net sft, then close it until ref count | ||
| 751 | ; is 0. | ||
| 752 | ; | ||
| 753 | TEST ES:[DI].sf_flags,sf_isNet | ||
| 754 | JNZ LRUClose | ||
| 755 | IF INSTALLED | ||
| 756 | Invoke CheckShare | ||
| 757 | JZ LRUDone | ||
| 758 | ENDIF | ||
| 759 | ; | ||
| 760 | ; Repeat close until ref count is 0 | ||
| 761 | ; | ||
| 762 | LRUClose: | ||
| 763 | Context DS | ||
| 764 | LES DI,ThisSFT | ||
| 765 | CMP ES:[DI].sf_ref_count,0 ; is ref count still <> 0? | ||
| 766 | JZ LRUDone ; nope, all done | ||
| 767 | |||
| 768 | ; Message 1,"LRUFCB: closing " | ||
| 769 | ; MessageNum <WORD PTR THISSFT+2> | ||
| 770 | ; Message 1,":" | ||
| 771 | ; MessageNum <WORD PTR THISSFT> | ||
| 772 | |||
| 773 | Invoke DOS_Close | ||
| 774 | jnc LRUClose ; no error => clean up | ||
| 775 | cmp al,error_invalid_handle | ||
| 776 | jz LRUClose | ||
| 777 | stc | ||
| 778 | JMP short LRUDead | ||
| 779 | LRUDone: | ||
| 780 | XOR AL,AL | ||
| 781 | invoke BlastSFT ; fill SFT with 0 (AL) | ||
| 782 | LRUDead: | ||
| 783 | Invoke Restore_World | ||
| 784 | ASSUME DS:NOTHING | ||
| 785 | LES DI,ThisSFT | ||
| 786 | Assert ISSFT,<ES,DI>,"LRUFCB return" | ||
| 787 | retnc | ||
| 788 | MOV AL,error_FCB_unavailable | ||
| 789 | return | ||
| 790 | EndProc LRUFCB | ||
| 791 | |||
| 792 | Break <FCBRegen - regenerate a sft from the info in the FCB> | ||
| 793 | |||
| 794 | ; | ||
| 795 | ; FCBRegen - examine reserved field of FCB and attempt to generate the SFT | ||
| 796 | ; from it. | ||
| 797 | ; | ||
| 798 | ; Inputs: DS:SI point to FCB | ||
| 799 | ; Outputs: carry clear Filled in SFT | ||
| 800 | ; Carry set unrecoverable error | ||
| 801 | ; Registers modified: all | ||
| 802 | |||
| 803 | Procedure FCBRegen,NEAR | ||
| 804 | ASSUME DS:NOTHING,ES:NOTHING | ||
| 805 | ; | ||
| 806 | ; General data filling. Mode is sf_isFCB + open_for_both, date/time we do | ||
| 807 | ; not fill, size we do no fill, position we do not fill, | ||
| 808 | ; bit 14 of flags = TRUE, other bits = FALSE | ||
| 809 | ; | ||
| 810 | MOV AL,[SI].fcb_l_drive | ||
| 811 | ; | ||
| 812 | ; We discriminate based on the first two bits in the reserved field. | ||
| 813 | ; | ||
| 814 | TEST AL,FCBSPECIAL ; check for no sharing test | ||
| 815 | JZ RegenNoSharing ; yes, go regen from no sharing | ||
| 816 | ; | ||
| 817 | ; The FCB is for a network or a sharing based system. At this point we have | ||
| 818 | ; already closed the SFT for this guy and reconnection is impossible. | ||
| 819 | ; | ||
| 820 | ; Remember that he may have given us a FCB with bogus information in it. | ||
| 821 | ; Check to see if sharing is present or if the redir is present. If either is | ||
| 822 | ; around, presume that we have cycled out the FCB and give the hard error. | ||
| 823 | ; Otherwise, just return with carry set. | ||
| 824 | ; | ||
| 825 | invoke CheckShare ; test for sharer | ||
| 826 | JNZ RegenFail ; yep, fail this. | ||
| 827 | MOV AX,multNet SHL 8 ; install check on multnet | ||
| 828 | INT 2FH | ||
| 829 | OR AL,AL ; is it there? | ||
| 830 | JZ RegenDead ; no, just fail the operation | ||
| 831 | RegenFail: | ||
| 832 | MOV AX,User_In_AX | ||
| 833 | cmp AH,fcb_close | ||
| 834 | jz RegenDead | ||
| 835 | invoke FCBHardErr ; massive hard error. | ||
| 836 | RegenDead: | ||
| 837 | STC | ||
| 838 | return ; carry set | ||
| 839 | ; | ||
| 840 | ; Local FCB without sharing. Check to see if sharing is loaded. If so | ||
| 841 | ; fail the operation. | ||
| 842 | ; | ||
| 843 | RegenNoSharing: | ||
| 844 | invoke CheckShare ; Sharing around? | ||
| 845 | JNZ RegenFail | ||
| 846 | ; | ||
| 847 | ; Find an SFT for this guy. | ||
| 848 | ; | ||
| 849 | invoke LRUFcb | ||
| 850 | retc | ||
| 851 | MOV ES:[DI].sf_mode,SF_IsFCB + open_for_both + sharing_compat | ||
| 852 | AND AL,3Fh ; get drive number for flags | ||
| 853 | CBW | ||
| 854 | OR AX,sf_close_noDate ; normal FCB operation | ||
| 855 | ; | ||
| 856 | ; The bits field consists of the upper two bits (dirty and device) from the | ||
| 857 | ; SFT and the low 4 bits from the open mode. | ||
| 858 | ; | ||
| 859 | MOV CL,[SI].FCB_nsl_bits ; stick in dirty bits. | ||
| 860 | MOV CH,CL | ||
| 861 | AND CH,0C0h ; mask off the dirty/device bits | ||
| 862 | OR AL,CH | ||
| 863 | AND CL,access_mask ; get the mode bits | ||
| 864 | MOV BYTE PTR ES:[DI].sf_mode,CL | ||
| 865 | MOV ES:[DI].sf_flags,AX ; initial flags | ||
| 866 | MOV AX,Proc_ID | ||
| 867 | MOV ES:[DI].sf_PID,AX | ||
| 868 | SaveReg <DS,SI,ES,DI> | ||
| 869 | Context ES | ||
| 870 | MOV DI,OFFSET DOSGroup:Name1 | ||
| 871 | MOV CX,8 | ||
| 872 | INC SI ; Skip past drive byte to name in FCB | ||
| 873 | RegenCopyName2: | ||
| 874 | LODSB | ||
| 875 | |||
| 876 | IF DBCS ;AN000; | ||
| 877 | invoke testkanj ;AN000; | ||
| 878 | jz notkanj9 ;AN000; | ||
| 879 | STOSB ;AN000; | ||
| 880 | DEC CX ;AN000; | ||
| 881 | JCXZ DoneNam2 ;AN000; ; Ignore split kanji char error | ||
| 882 | LODSB ;AN000; | ||
| 883 | jmp short StuffChar2 ;AN000; | ||
| 884 | ;AN000; | ||
| 885 | notkanj9: ;AN000; | ||
| 886 | ENDIF ;AN000; | ||
| 887 | |||
| 888 | Invoke UCase | ||
| 889 | StuffChar2: | ||
| 890 | STOSB | ||
| 891 | LOOP RegenCopyName2 | ||
| 892 | DoneNam2: | ||
| 893 | Context DS | ||
| 894 | MOV [ATTRIB],attr_hidden + attr_system + attr_directory | ||
| 895 | ; Must set this to something interesting | ||
| 896 | ; to call DEVNAME. | ||
| 897 | Invoke DevName ; check for device | ||
| 898 | ASSUME DS:NOTHING,ES:NOTHING | ||
| 899 | RestoreReg <DI,ES,SI,DS> | ||
| 900 | JC RegenFileNoSharing ; not found on device list => file | ||
| 901 | ; | ||
| 902 | ; Device found. We can ignore disk-specific info | ||
| 903 | ; | ||
| 904 | MOV BYTE PTR ES:[DI].sf_flags,BH ; device parms | ||
| 905 | MOV ES:[DI].sf_attr,0 ; attribute | ||
| 906 | LDS SI,DEVPT ; get device driver | ||
| 907 | MOV WORD PTR ES:[DI].sf_devptr,SI | ||
| 908 | MOV WORD PTR ES:[DI].sf_devptr+2,DS | ||
| 909 | return ; carry is clear | ||
| 910 | |||
| 911 | RegenDeadJ: | ||
| 912 | JMP RegenDead | ||
| 913 | ; | ||
| 914 | ; File found. Just copy in the remaining pieces. | ||
| 915 | ; | ||
| 916 | RegenFileNoSharing: | ||
| 917 | MOV AX,ES:[DI].sf_flags | ||
| 918 | AND AX,03Fh | ||
| 919 | SaveReg <DS,SI> | ||
| 920 | Invoke Find_DPB | ||
| 921 | MOV WORD PTR ES:[DI].sf_devptr,SI | ||
| 922 | MOV WORD PTR ES:[DI].sf_devptr+2,DS | ||
| 923 | RestoreReg <SI,DS> | ||
| 924 | jc RegenDeadJ ; if find DPB fails, then drive | ||
| 925 | ; indicator was bogus | ||
| 926 | MOV AX,[SI].FCB_nsl_dirsec | ||
| 927 | MOV WORD PTR ES:[DI].sf_dirsec,AX | ||
| 928 | MOV WORD PTR ES:[DI].sf_dirsec+2,0 ;AN000;>32mb | ||
| 929 | MOV AX,[SI].FCB_nsl_firclus | ||
| 930 | MOV ES:[DI].sf_firclus,AX | ||
| 931 | MOV ES:[DI].sf_lstclus,AX | ||
| 932 | MOV AL,[SI].FCB_nsl_dirpos | ||
| 933 | MOV ES:[DI].sf_dirpos,AL | ||
| 934 | INC ES:[DI].sf_ref_count ; Increment reference count. | ||
| 935 | ; Existing FCB entries would be | ||
| 936 | ; flushed unnecessarily because of | ||
| 937 | ; check in CheckFCB of the ref_count. | ||
| 938 | ; July 22/85 - BAS | ||
| 939 | LEA SI,[SI].FCB_name | ||
| 940 | LEA DI,[DI].sf_name | ||
| 941 | MOV CX,fcb_extent-fcb_name | ||
| 942 | RegenCopyName: | ||
| 943 | LODSB | ||
| 944 | |||
| 945 | IF DBCS ;AN000; | ||
| 946 | invoke testkanj | ||
| 947 | jz notkanj1 | ||
| 948 | STOSB | ||
| 949 | DEC CX | ||
| 950 | JCXZ DoneNam ; Ignore split kanji char error | ||
| 951 | LODSB | ||
| 952 | jmp short StuffChar | ||
| 953 | |||
| 954 | notkanj1: | ||
| 955 | ENDIF ;AN000; | ||
| 956 | |||
| 957 | Invoke UCase | ||
| 958 | StuffChar: | ||
| 959 | STOSB | ||
| 960 | LOOP RegenCopyName | ||
| 961 | DoneNam: | ||
| 962 | clc | ||
| 963 | return | ||
| 964 | EndProc FCBRegen | ||
| 965 | |||
| 966 | ; | ||
| 967 | ; BlastSFT - fill SFT with garbage | ||
| 968 | ; | ||
| 969 | ; Inputs: ES:DI point to SFT | ||
| 970 | ; AL has fill | ||
| 971 | ; Outputs: SFT is filled with nonsense | ||
| 972 | ; *FLAGS PRESERVED* | ||
| 973 | ; Registers modified: CX | ||
| 974 | |||
| 975 | Procedure BlastSFT,NEAR | ||
| 976 | SaveReg <DI> | ||
| 977 | MOV CX,SIZE sf_entry | ||
| 978 | REP STOSB | ||
| 979 | RestoreReg <DI> | ||
| 980 | MOV ES:[DI].sf_ref_count,0 ; set ref count | ||
| 981 | MOV ES:[DI].sf_LRU,0 ; set lru | ||
| 982 | MOV ES:[DI].sf_OpenAge,-1 ; Set open age | ||
| 983 | return | ||
| 984 | EndProc BlastSFT | ||
| 985 | |||
| 986 | Break <CheckFCB - see if the SFT pointed to by the FCB is still OK> | ||
| 987 | |||
| 988 | ; CheckFCB - examine an FCB and its contents to see if it needs to be | ||
| 989 | ; regenerated. | ||
| 990 | ; | ||
| 991 | ; Inputs: DS:SI point to FCB (not extended) | ||
| 992 | ; AL is SFT index | ||
| 993 | ; Outputs: Carry Set - FCB needs to be regened | ||
| 994 | ; Carry clear - FCB is OK. ES:DI point to SFT | ||
| 995 | ; Registers modified: AX and BX | ||
| 996 | |||
| 997 | Procedure CheckFCB,NEAR | ||
| 998 | ASSUME DS:NOTHING,ES:NOTHING | ||
| 999 | LES DI,sftFCB | ||
| 1000 | CMP BYTE PTR ES:[DI].SFCount,AL | ||
| 1001 | JC BadSFT | ||
| 1002 | MOV BL,SIZE sf_entry | ||
| 1003 | MUL BL | ||
| 1004 | LEA DI,[DI].sftable | ||
| 1005 | ADD DI,AX | ||
| 1006 | MOV AX,Proc_ID | ||
| 1007 | CMP ES:[DI].sf_PID,AX | ||
| 1008 | JNZ BadSFT ; must match process | ||
| 1009 | CMP ES:[DI].sf_ref_count,0 | ||
| 1010 | JZ BadSFT ; must also be in use | ||
| 1011 | MOV AL,[SI].FCB_l_Drive | ||
| 1012 | TEST AL,FCBSPECIAL ; a special FCB? | ||
| 1013 | JZ CheckNoShare ; No. try local or device | ||
| 1014 | ; | ||
| 1015 | ; Since we are a special FCB, try NOT to use a bogus test instruction. | ||
| 1016 | ; FCBSHARE is a superset of FCBNETWORK. | ||
| 1017 | ; | ||
| 1018 | PUSH AX | ||
| 1019 | AND AL,FCBMASK | ||
| 1020 | CMP AL,FCBSHARE ; net FCB? | ||
| 1021 | POP AX | ||
| 1022 | JNZ CheckNet ; yes | ||
| 1023 | ; | ||
| 1024 | ;----- In share support ----- | ||
| 1025 | ; | ||
| 1026 | if installed | ||
| 1027 | Call JShare + 11 * 4 | ||
| 1028 | else | ||
| 1029 | Call ShChk | ||
| 1030 | endif | ||
| 1031 | JC BadSFT | ||
| 1032 | JMP SHORT CheckD | ||
| 1033 | ; | ||
| 1034 | ;----- End in share support ----- | ||
| 1035 | ; | ||
| 1036 | CheckFirClus: | ||
| 1037 | CMP BX,ES:[DI].sf_firclus | ||
| 1038 | JNZ BadSFT | ||
| 1039 | CheckD: AND AL,3Fh | ||
| 1040 | MOV AH,BYTE PTR ES:[DI].sf_flags | ||
| 1041 | AND AH,3Fh | ||
| 1042 | CMP AH,AL | ||
| 1043 | retz ; carry is clear | ||
| 1044 | BadSFT: STC | ||
| 1045 | return ; carry is clear | ||
| 1046 | CheckNet: | ||
| 1047 | ; | ||
| 1048 | ;----- In net support ----- | ||
| 1049 | ; | ||
| 1050 | ; MOV AX,[SI].FCB_net_handle | ||
| 1051 | ; CMP AX,WORD PTR ES:[DI].sf_NETID+4 | ||
| 1052 | ; JNZ BadSFT | ||
| 1053 | ; MOV AX,WORD PTR [SI].FCB_netID | ||
| 1054 | ; CMP AX,WORD PTR ES:[DI].sf_netid | ||
| 1055 | ; JNZ BadSFT | ||
| 1056 | MOV AX,WORD PTR [SI].FCB_netID ;AN000;IFS.DOS 4.00 | ||
| 1057 | CMP AX,WORD PTR ES:[DI].sf_serial_ID ;AN000;IFS.DOS 4.00 | ||
| 1058 | JNZ BadSFT | ||
| 1059 | ; | ||
| 1060 | ;----- END In net support ----- | ||
| 1061 | ; | ||
| 1062 | return | ||
| 1063 | |||
| 1064 | CheckNoShare: | ||
| 1065 | TEST AL,FCBDEVICE ; Device? | ||
| 1066 | JNZ CheckNoShareDev ; Yes | ||
| 1067 | ; | ||
| 1068 | ; Check no sharing local file | ||
| 1069 | ; | ||
| 1070 | MOV BX,[SI].FCB_nsl_Dirsec | ||
| 1071 | CMP WORD PTR ES:[DI].sf_dirsec+2,0 ;AN000;F.C. >32mb | ||
| 1072 | JNZ BadSFt ;AN000;F.C. >32mb | ||
| 1073 | |||
| 1074 | CMP BX,WORD PTR ES:[DI].sf_dirsec ;AN000;F.C. >32mb | ||
| 1075 | JNZ BadSFT | ||
| 1076 | MOV BL,[SI].FCB_nsl_Dirpos | ||
| 1077 | CMP BL,ES:[DI].sf_dirpos | ||
| 1078 | JNZ BadSFt | ||
| 1079 | ; | ||
| 1080 | ; Since the bits field comes from two different spots, compare them separately. | ||
| 1081 | ; | ||
| 1082 | MOV BL,[SI].FCB_nsl_bits | ||
| 1083 | MOV BH,BYTE PTR ES:[DI].sf_flags | ||
| 1084 | XOR BH,BL | ||
| 1085 | AND BH,0C0h | ||
| 1086 | JNZ BadSFT ; dirty/device bits are different | ||
| 1087 | XOR BL,BYTE PTR ES:[DI].sf_mode | ||
| 1088 | AND BL,access_mask | ||
| 1089 | JNZ BadSFT ; access modes are different | ||
| 1090 | ; Make sure that the names are the same in the FCB and the SFT | ||
| 1091 | ; This case can appear under the following scenario: | ||
| 1092 | ; Create FOO | ||
| 1093 | ; Rename FOO -> BAR | ||
| 1094 | ; Open BAR | ||
| 1095 | ; The SFT will still contain the name for the old file name. | ||
| 1096 | ; July 30/85 - BAS | ||
| 1097 | PUSH DI | ||
| 1098 | PUSH SI | ||
| 1099 | LEA DI,[DI].sf_name | ||
| 1100 | LEA SI,[SI].fcb_name | ||
| 1101 | MOV CX,11 | ||
| 1102 | REPE CMPSB | ||
| 1103 | POP SI | ||
| 1104 | POP DI | ||
| 1105 | JNZ BadSFT | ||
| 1106 | MOV BX,[SI].FCB_nsl_firclus | ||
| 1107 | JMP CheckFirClus | ||
| 1108 | |||
| 1109 | CheckNoShareDev: | ||
| 1110 | MOV BX,WORD PTR [SI].FCB_nsld_drvptr | ||
| 1111 | CMP BX,WORD PTR ES:[DI].sf_devptr | ||
| 1112 | JNZ BadSFT | ||
| 1113 | MOV BX,WORD PTR [SI].FCB_nsld_drvptr + 2 | ||
| 1114 | CMP BX,WORD PTR ES:[DI].sf_devptr + 2 | ||
| 1115 | JNZ BadSFT | ||
| 1116 | JMP CheckD | ||
| 1117 | |||
| 1118 | EndProc CheckFCB | ||
| 1119 | |||
| 1120 | Break <SFTFromFCB - take a FCB and obtain a SFT from it> | ||
| 1121 | |||
| 1122 | ; | ||
| 1123 | ; SFTFromFCB - the workhorse of this compatability crap. Check to see if | ||
| 1124 | ; the SFT for the FCB is Good. If so, make ThisSFT point to it. If not | ||
| 1125 | ; good, get one from the cache and regenerate it. Overlay the LRU field | ||
| 1126 | ; with PID | ||
| 1127 | ; | ||
| 1128 | ; Inputs: DS:SI point to FCB | ||
| 1129 | ; Outputs: ThisSFT point to appropriate SFT | ||
| 1130 | ; Carry clear -> OK ES:DI -> SFT | ||
| 1131 | ; Carry set -> error in ax | ||
| 1132 | ; Registers modified: ES,DI, AX | ||
| 1133 | |||
| 1134 | Procedure SFTFromFCB,NEAR | ||
| 1135 | ASSUME DS:NOTHING,ES:NOTHING | ||
| 1136 | SaveReg <AX,BX> | ||
| 1137 | MOV AL,[SI].fcb_sfn ; set SFN for check | ||
| 1138 | invoke CheckFCB | ||
| 1139 | RestoreReg <BX,AX> | ||
| 1140 | MOV WORD PTR ThisSFT,DI ; set thissft | ||
| 1141 | MOV WORD PTR ThisSFT+2,ES | ||
| 1142 | JNC SetSFT ; no problems, just set thissft | ||
| 1143 | |||
| 1144 | fmt typFCB,LevCheck,<"FCB $x:$x does not match SFT $x:$x\n">,<DS,SI,ES,DI> | ||
| 1145 | |||
| 1146 | Invoke Save_World | ||
| 1147 | invoke FCBRegen | ||
| 1148 | Invoke Restore_World ; restore world | ||
| 1149 | MOV AX,EXTERR | ||
| 1150 | retc | ||
| 1151 | |||
| 1152 | ; Message 1,<"FCBRegen Succeeded",13,10> | ||
| 1153 | |||
| 1154 | SetSFT: LES DI,ThisSFT | ||
| 1155 | PUSH Proc_ID ; set process id | ||
| 1156 | POP ES:[DI].sf_PID | ||
| 1157 | return ; carry is clear | ||
| 1158 | EndProc SFTFromFCB | ||
| 1159 | |||
| 1160 | Break <FCBHardErr - generate INT 24 for hard errors on FCBS> | ||
| 1161 | |||
| 1162 | ; | ||
| 1163 | ; FCBHardErr - signal to a user app that he is trying to use an | ||
| 1164 | ; unavailable FCB. | ||
| 1165 | ; | ||
| 1166 | ; Inputs: none. | ||
| 1167 | ; Outputs: none. | ||
| 1168 | ; Registers modified: all | ||
| 1169 | ; | ||
| 1170 | |||
| 1171 | Procedure FCBHardErr,NEAR | ||
| 1172 | ASSUME DS:NOTHING,ES:NOTHING | ||
| 1173 | MOV AX,error_FCB_Unavailable | ||
| 1174 | MOV [ALLOWED],allowed_FAIL | ||
| 1175 | LES BP,[THISDPB] | ||
| 1176 | MOV DI,1 ; Fake some registers | ||
| 1177 | MOV CX,DI | ||
| 1178 | MOV DX,ES:[BP.dpb_first_sector] | ||
| 1179 | invoke HARDERR | ||
| 1180 | STC | ||
| 1181 | return | ||
| 1182 | EndProc FCBHardErr | ||
| 1183 | |||
| 1184 | CODE ENDS | ||
| 1185 | END | ||