]> wirehaze git hosting - MS-DOS.git/blob - v4.0/src/SELECT/ROUTINE2.ASM

wirehaze git hosting

MZ is back!
[MS-DOS.git] / v4.0 / src / SELECT / ROUTINE2.ASM
1 ;***************************************************************************
2 ; Subroutines which are called by the macros in MACROS.INC.
3 ; File: ROUTINE2.ASM
4 ; Latest Change Date: August 04, 1987
5 ;
6 ; This is a stand alone module and is meant to be linked with the calling
7 ; program.
8 ;
9 ;***************************************************************************
10 .ALPHA ;AN000;
11 ;**********************************************************************
12 DATA SEGMENT BYTE PUBLIC 'DATA' ;AN000;
13
14 PATH_STRING DW 0 ;AN000;
15 STRING_SIZE DW 0 ;AN000;
16 PATH_PTR DW 0 ;AN000;
17 PATH_SIZE DW 0 ;AN000;
18 MAX_CHAR DW 0 ;AN000;
19 CHAR_COUNT DW 0 ;AN000;
20
21
22 SEARCH_FLAG DB 0 ;AN000;
23
24 PERIOD EQU 00000001B ;AN000;
25 SLASH_FOUND EQU 00000010B ;AN000;
26
27
28 RESET_PERIOD EQU 11111110B ;AN000;
29 RESET_SLASH_FOUND EQU 11111101B ;AN000;
30
31 INVALID_STRING DB '"/\[]:|<>+=;, ' ;AN000;
32 END_INVALID_STRING EQU $ ;AN000;
33 SIZE_INVALID_STR EQU END_INVALID_STRING - INVALID_STRING ;AN000;
34
35 ZEROED_CHAR DB 0 ;AN000;
36 DB 0 ;AN000;
37
38 SEP_POSITION DW 0 ;AN000;
39 NUM_PATHS DW 0 ;AN000;
40
41
42 ERR_INVALID_DRV EQU 1 ;AN000;
43 ERR_NO_DRIVE EQU 2 ;AN000;
44 ERR_DRIVE EQU 3 ;AN000;
45 ERR_LEADING_SLASH EQU 4 ;AN000;
46 ERR_NO_SLASH EQU 5 ;AN000;
47 ERR_LAST_SLASH EQU 6 ;AN000;
48 ERR_INVALID_CHAR EQU 7 ;AN000;
49
50 OLD_ATTRIB DW 0 ;AN000;
51 NEW_ATTRIB DW 0 ;AN000;
52 WAY DW 0 ;AN000;
53
54
55
56 PUBLIC CHK_W_PROTECT_FLAG ;AN000;
57 PUBLIC W_PROTECT_FLAG ;AN000;
58
59 W_P_FILENAME_A DB 'A:\',12 DUP(0), 0 ;AC000;JW
60 W_P_FILENAME_B DB 'B:\',12 DUP(0), 0 ;AN000;JW
61 CHK_W_PROTECT_FLAG DB 0 ;AN000;
62 W_PROTECT_FLAG DB 0 ;AN000;
63 DRIVE_FLAG DB ? ;AN000;JW
64
65
66 NUM_FILES DW 0 ;AN000;
67 LIST_TYPE DW 0 ;AN000;
68 STR_PTR DW 0 ;AN000;
69 FILE_PTR DW 0 ;AN000;
70
71
72
73 DATA ENDS ;AN000; DATA
74 ;**********************************************************************
75 ;
76 .XLIST ;AN000;
77 INCLUDE STRUC.INC ;AN000;
78 INCLUDE MACROS.INC ;AN000;
79 INCLUDE VARSTRUC.INC ;AN000;
80 INCLUDE EXT.INC ;AN000;
81 INCLUDE MAC_EQU.INC ;AN000;
82 EXTRN EXIT_DOS:FAR ;AN000;
83 EXTRN POS_ZERO:FAR ;AN000;
84 EXTRN HOOK_INT_24:FAR ;AN000;
85 EXTRN RESTORE_INT_24:FAR ;AN000;
86 EXTRN GGET_STATUS:FAR ;AN000;
87 .LIST ;AN000;
88 ;
89 ;
90 ;**********************************************************************
91 CODE_FAR SEGMENT PARA PUBLIC 'CODE' ;AN000; Segment for far routine
92 ASSUME CS:CODE_FAR,DS:DATA ;AN000;
93 ;
94 ;********************************************************************************
95 ; CHECK_DOS_PATH_ROUTINE: Check to see if the sepecified path for the DOS
96 ; SET PATH command is valid.
97 ;
98 ; INPUT:
99 ; SI = Points to an ASCII-N string containing the path to check. There sould
100 ; be an extra byte following the string to facilitate changing the string
101 ; into an ASCII-Z string.
102 ;
103 ; OUTPUT:
104 ; If CY = 0, the path is valid.
105 ; If CY = 1, The path is NOT valid:
106 ;
107 ;********************************************************************************
108 PUBLIC CHECK_DOS_PATH_ROUTINE ;AN000;
109 CHECK_DOS_PATH_ROUTINE PROC FAR ;AN000;
110 ;
111 MOV PATH_PTR, SI ;AN000; Get the pointer from the path
112 MOV AX, [SI] ;AN000; Get the lenth of the path string
113 .IF < AX EQ 0 > ;AN000; If the length is zero then return that
114 JMP NO_ERROR_DOS_PATH ;AN000; the path is valid.
115 .ENDIF ;AN000;
116 MOV PATH_SIZE, AX ;AN000; Save the size of the string
117 ADD SI, 2 ;AN000; Adjust path pointer for length word
118 ;
119 .REPEAT ;AN000; Check all the path names in the string
120 MOV AL, ';' ;AN000; separator between filenames
121 MOV CX, PATH_PTR ;AN000; Get the pointer to the path
122 ADD CX, 2 ;AN000; Point to the start of the string
123 ADD CX, PATH_SIZE ;AN000; Add the size of the path
124 SUB CX, SI ;AN000; Subtract current pointer - Get length of string remaining
125 CALL ISOLATE_NEXT_PATH ;AN000; Make the next path name into an ASCII-Z string
126 PUSH SEP_POSITION ;AN000; Save the position of the path seperator
127 PUSH WORD PTR ZEROED_CHAR ;AN000; Save the character that was made into a zero
128 MOV CX, SEP_POSITION ;AN000;
129 SUB CX, SI ;AN000; Get the length of the string
130 MOV AX, 0101H ;AN000;
131 CALL FAR PTR CHECK_VALID_PATH ;AN000; Check if it is a valid filename
132 POP WORD PTR ZEROED_CHAR ;AN000;
133 POP SEP_POSITION ;AN000;
134 CALL RESTORE_SEPARATOR ;AN000; Restore the character between the path names
135 .IF < C > ;AN000; Was the file name not valid?
136 JMP ERROR_DOS_PATH ;AN000; Exit the subroutine
137 .ENDIF ;AN000;
138 MOV SI, DI ;AN000; Get the pointer to the next path name
139 .UNTIL < ZERO SI > ;AN000; If zero, all path names have been examined.
140 NO_ERROR_DOS_PATH: ;AN000;
141 CLC ;AN000;
142 JMP EXIT_DOS_PATH ;AN000;
143 ERROR_DOS_PATH: ;AN000;
144 STC ;AN000;
145 EXIT_DOS_PATH: ;AN000;
146 RET ;AN000;
147 ;
148 CHECK_DOS_PATH_ROUTINE ENDP ;AN000;
149 ;
150 ;
151 PUBLIC CHECK_VALID_PATH ;AN000;
152 ;********************************************************************************
153 ; CHECK_VALID_PATH: Check to see if the sepecified path is valid.
154 ;
155 ; INPUT:
156 ; SI = Points to an ASCII-Z string containing the path to check. There sould
157 ; be an extra byte following the string to facilitate changing the string
158 ; into an ASCII-Z string.
159 ;
160 ; CX = The size of the string containing the path. The zero byte at the end
161 ; of the string is NOT included in the length.
162 ;
163 ; AL = 0: Drive letter cannot be specified.
164 ; = 1: Drive letter is optional and can be specified.
165 ; = 2: Drive letter must be specified.
166 ;
167 ; AH = 0: First non-drive character cannot be a backslash ('\')
168 ; = 1: First non-drive character may be a backslash ('\')
169 ; = 2: First non-drive character must be a backslash ('\')
170 ;
171 ; OUTPUT:
172 ; If CY = 0, the path is valid.
173 ; If CY = 1, The path is NOT valid:
174 ; AX = 1, The drive specified is invalid.
175 ; = 2, There was no drive specified.
176 ; = 3, There was a drive specified.
177 ; = 4, There was a leading backslash
178 ; = 5, The leading backslash was NOT present.
179 ; = 6, There was a trailing backslash.
180 ;
181 ;********************************************************************************
182 CHECK_VALID_PATH PROC FAR ;AN000;
183 ;
184 PUSH DI ;AN000;
185 MOV STRING_SIZE, CX ;AN000; Save the size of the string
186 MOV PATH_STRING, SI ;AN000; Save the pointer to the string
187 CALL CHECK_VALID_DRIVE ;AN000; See if there is a valid drive
188 .IF < C > ;AN000; Is the drive specified invalid?
189 MOV AX, ERR_INVALID_DRV ;AN000; Return this error code
190 JMP EXIT_CHK_DRV ;AN000; Exit the subroutine
191 .ENDIF ;AN000;
192 .IF < BX EQ 0 > ;AN000; No drive sepecified?
193 .IF < AL EQ 2 > ;AN000; Must the drive be specified?
194 MOV AX, ERR_NO_DRIVE ;AN000; Return this error code
195 JMP EXIT_CHK_DRV ;AN000; Exit the subroutine
196 .ENDIF ;AN000;
197 .ELSE ;AN000; Otherwise, the drive WAS specified.
198 .IF < AL EQ 0 > ;AN000; The drive cannot be specified
199 MOV AX, ERR_DRIVE ;AN000; Return this error code
200 JMP EXIT_CHK_DRV ;AN000; Exit the subroutine
201 .ENDIF ;AN000;
202 ADD SI, 2 ;AN000; Push pointer past the drive
203 .ENDIF ;AN000;
204 .IF < <BYTE PTR [SI]> EQ '\' > ;AN000; Is the next byte a backslash?
205 .IF < AH EQ 0 > ;AN000; Is one permitted?
206 MOV AX, ERR_LEADING_SLASH ;AN000; No! Return this error code
207 JMP EXIT_CHK_DRV ;AN000; Exit the subroutine
208 .ELSE ;AN000; Otherwise, one allowed.
209 INC SI ;AN000; Push pointer past \
210 .ENDIF ;AN000;
211 .ELSE ;AN000; Otherwise, byte not a backslash
212 .IF < AH EQ 2 > ;AN000; Was one required?
213 MOV AX, ERR_NO_SLASH ;AN000; If so, return this error code
214 JMP EXIT_CHK_DRV ;AN000; Exit from this subroutine
215 .ENDIF ;AN000;
216 .ENDIF ;AN000;
217 ;
218 MOV NUM_PATHS, 0 ;AN000;
219 .REPEAT ;AN000; Check all the path names in the string
220 MOV AL, '\' ;AN000; Separator between filenames
221 MOV CX, PATH_STRING ;AN000;
222 ADD CX, STRING_SIZE ;AN000;
223 SUB CX, SI ;AN000;
224 .IF < NUM_PATHS EQ 0 > AND ;AN000; If this is the first path checked...and
225 .IF < CX EQ 0 > ;AN000; If the length of the path is zero...
226 JMP EXIT_NO_ERROR ;AN000; Exit with no error
227 .ENDIF ;AN000;
228 CALL ISOLATE_NEXT_PATH ;AN000; Make the next path name into an ASCII-Z string
229 CALL CHECK_VALID_FILENAME ;AN000; Check if it is a valid filename
230 CALL RESTORE_SEPARATOR ;AN000; Restore the character between the path names
231 .IF < C > ;AN000; Was the file name not valid?
232 .IF < NUM_PATHS EQ 0 > ;AN000;
233 .LEAVE ;AN000;
234 .ELSE ;AN000;
235 MOV AX, ERR_INVALID_CHAR ;AN000; If not, return this error code
236 JMP EXIT_CHK_DRV ;AN000; Exit the subroutine
237 .ENDIF ;AN000;
238 .ENDIF ;AN000;
239 MOV SI, DI ;AN000; Get the pointer to the next path name
240 .UNTIL < ZERO SI > ;AN000; If zero, all path names have been examined.
241 ;
242 MOV SI, PATH_STRING ;AN000; Get the pointer to the whole string
243 ADD SI, STRING_SIZE ;AN000; Add the string length
244 DEC SI ;AN000; Point to the last character in the string
245 .IF < <BYTE PTR [SI]> EQ '\'> ;AN000; Is the last character a \ ?
246 MOV AX, ERR_LAST_SLASH ;AN000; If so, return this error code
247 JMP EXIT_CHK_DRV ;AN000; Exit from the subroutine
248 .ENDIF ;AN000;
249 EXIT_NO_ERROR: ;AN000;
250 CLC ;AN000; Indicate there were no errors
251 JMP EXIT_CHECK_PATH ;AN000;
252 ;
253 EXIT_CHK_DRV: ;AN000;
254 STC ;AN000; Indicate that there were errors
255 EXIT_CHECK_PATH: ;AN000;
256 POP DI ;AN000;
257 RET ;AN000;
258 ;
259 ;
260 CHECK_VALID_PATH ENDP ;AN000;
261 ;********************************************************************************
262 ; CHECK_VALID_DRIVE: Check to see if there is a drive specified on the path and
263 ; if there is, is it valid.
264 ;
265 ; INPUT:
266 ; SI - Points to a string containing the path to search.
267 ;
268 ; OUTPUT:
269 ; If CY = 1, the drive is specified and is invalid
270 ; If CY = 0, The drive might be specified and is valid
271 ; BX = 0: The drive is NOT specified.
272 ; = 1: The drive IS specified.
273 ;
274 ;
275 ;********************************************************************************
276 CHECK_VALID_DRIVE PROC NEAR ;AN000;
277 ;
278 PUSH AX ;AN000; Push all registers used
279 .IF < <BYTE PTR [SI+1]> EQ ':' > ;AN000; Is the second character in the string a ':'
280 MOV AL, [SI] ;AN000; If so, get the first character
281 .IF < AL AE 'A' > AND ;AN000; Is it a capital letter?
282 .IF < AL BE 'Z' > ;AN000;
283 CLC ;AN000; If so, drive valid.
284 MOV BX, 1 ;AN000; Indicate the drive exists
285 .ELSEIF < AL AE 'a' > AND ;AN000; Else, is the drive a lowercase letter?
286 .IF < AL BE 'z' > ;AN000;
287 CLC ;AN000; If so, the drive is valid
288 MOV BX, 1 ;AN000; Indicate that the drive exists
289 .ELSE ;AN000; Otherwise...
290 STC ;AN000; The drive is not valid
291 .ENDIF ;AN000;
292 .ELSE ;AN000;
293 CLC ;AN000; Indicate there were no errors
294 MOV BX, 0 ;AN000; The drive does not exist
295 .ENDIF ;AN000;
296 POP AX ;AN000;
297 ;
298 RET ;AN000;
299 ;
300 CHECK_VALID_DRIVE ENDP ;AN000;
301 ;********************************************************************************
302 ; CHECK_VALID_FILENAME: Check to see if a filename is valid.
303 ;
304 ; INPUT:
305 ; SI - Points to an ASCII-Z string containing the filename to examine.
306 ;
307 ; OUTPUT:
308 ; If CY = 1, The filename is NOT valid.
309 ; If CY = 0, the filename IS valid.
310 ;
311 ;
312 ;********************************************************************************
313 CHECK_VALID_FILENAME PROC NEAR ;AN000;
314 ;
315 INC NUM_PATHS ;AN000;
316 AND SEARCH_FLAG, RESET_PERIOD ;AN000; Indicate no periods have been found yet
317 MOV MAX_CHAR, 8 ;AN000; Up to 8 characters can be specified
318 MOV CHAR_COUNT, 0 ;AN000; Number of character so far
319 MOV AL, [SI] ;AN000; Get the first character in the string
320 .WHILE < AL NE 0 > ;AN000; Repeat untill we reach the string's end
321 INC CHAR_COUNT ;AN000; Increment number of characters in path
322 MOV BX, CHAR_COUNT ;AN000;
323 .IF < BX A MAX_CHAR > AND ;AN000;
324 .IF < AL NE '.' > ;AN000;
325 JMP INVALID_CHAR ;AN000;
326 .ENDIF ;AN000;
327 .IF < AL B 20 > ;AN000; Is the character's code less than 20?
328 JMP INVALID_CHAR ;AN000; If so, it's invalid
329 .ELSE ;AN000; Otherwise...
330 CALL VALID_CHAR ;AN000; See if it's invalid
331 .IF < C > ;AN000; If so,
332 JMP INVALID_CHAR ;AN000; Exit the subroutine
333 .ENDIF ;AN000;
334 .ENDIF ;AN000;
335 .IF < AL EQ '.' > ;AN000; Is the character a period?
336 .IF < BIT SEARCH_FLAG AND PERIOD > ;AN000; Is this the first one?
337 JMP INVALID_CHAR ;AN000; If not, filename is invalid.
338 .ELSE ;AN000; Otherwise...
339 OR SEARCH_FLAG, PERIOD ;AN000; Indicate that ONE has been found
340 .IF < CHAR_COUNT EQ 1 > ;AN000; Were there any characters before the period
341 JMP INVALID_CHAR ;AN000; If not, this is an invalid path
342 .ENDIF ;AN000;
343 MOV MAX_CHAR, 3 ;AN000; Allow three characters after the period
344 MOV CHAR_COUNT, 0 ;AN000; No characters yet
345 .ENDIF ;AN000;
346 .ENDIF ;AN000;
347 INC SI ;AN000; Point to next character
348 MOV AL, [SI] ;AN000; Get that character
349 .ENDWHILE ;AN000;
350 .IF < CHAR_COUNT EQ 0 > AND ;AN000;
351 .IF < MAX_CHAR EQ 8 > ;AN000;
352 DEC NUM_PATHS ;AN000;
353 JMP INVALID_CHAR ;AN000;
354 .ENDIF ;AN000;
355 CLC ;AN000; Indicate the name is valid
356 JMP CK_V_FILENAME ;AN000; Exit.
357 ;
358 INVALID_CHAR: ;AN000; Indicate that the name is not valid
359 STC ;AN000;
360 CK_V_FILENAME: ;AN000;
361 RET ;AN000;
362 ;
363 CHECK_VALID_FILENAME ENDP ;AN000;
364 ;********************************************************************************
365 ; VALID_CHAR: Determine if a character is valid for a filename.
366 ;
367 ; INPUT:
368 ; AL = The character to check.
369 ;
370 ; OUTPUT:
371 ; If CY = 1, the character is not valid.
372 ; If CY = 0, the character IS valid.
373 ;
374 ;********************************************************************************
375 VALID_CHAR PROC NEAR ;AN000;
376 ;
377 PUSH CX ;AN000; Save the registers used.
378 PUSH DI ;AN000;
379 PUSH ES ;AN000;
380 ;
381 MOV DI, OFFSET INVALID_STRING ;AN000; Get the address of string containing invalid characters
382 PUSH DS ;AN000; Save the data segment
383 POP ES ;AN000; Make ES=DS
384 MOV CX, SIZE_INVALID_STR ;AN000; Get the size of the string
385 CLD ;AN000; Scan forward
386 REPNZ SCASB ;AN000; See if this character is in the invalid string
387 .IF < Z > ;AN000; If so,
388 STC ;AN000; Indicate the character is invalid
389 .ELSE ;AN000; Otherwise...
390 CLC ;AN000; Indicate the character is valid
391 .ENDIF ;AN000;
392 POP CX ;AN000; Restore the registers
393 POP DI ;AN000;
394 POP ES ;AN000;
395 RET ;AN000;
396 ;
397 VALID_CHAR ENDP ;AN000;
398 ;********************************************************************************
399 ; ISOLATE_NEXT_PATH: Search the filename for a '\'. If found, it is replaced
400 ; by a zero making the string into an ASCII-Z string.
401 ;
402 ; INPUT:
403 ; SI - Points to the first character in the path string
404 ; AL - Contains the character to search for
405 ; CX - Contains the length of the string
406 ;
407 ; OUTPUT:
408 ; DI - Points to the character following the next '\'
409 ; If this character is the last path element, DI = 0.
410 ;
411 ; ZEROED_CHAR is loaded with the character which is made into a zero.
412 ;
413 ;********************************************************************************
414 ISOLATE_NEXT_PATH PROC NEAR ;AN000;
415 ;
416 PUSH AX ;AN000; Save registers used.
417 PUSH BX ;AN000;
418 PUSH CX ;AN000;
419 PUSH SI ;AN000;
420 ;
421 PUSH ES ;AN000; Make ES = DS
422 PUSH DS ;AN000;
423 POP ES ;AN000;
424 MOV DI, SI ;AN000; Copy the string pointer
425 ; CX holds the length of string after the pointer DI
426 ; AL holds the character to search for
427 CLD ;AN000; Search in the forward direction
428 REPNZ SCASB ;AN000; Search...
429 JNZ END_FOUND ;AN000; If NZ, we reached the string's end
430 MOV ZEROED_CHAR, AL ;AN000; Character overwritten with zero
431 MOV SEP_POSITION, DI ;AN000; Save the position of overwritten char
432 DEC SEP_POSITION ;AN000;
433 MOV BYTE PTR [DI-1], 0 ;AN000; Make the character a zero
434 CMP CX,0 ;AN031; SEH User may have entered semicolon as last char, so check
435 JE END_FOUND2 ;AN031; SEH if it is last char instead of just a separator
436 JMP EXIT_ISOLATE ;AN000; Exit the subroutine
437 END_FOUND: ;AN000;
438 MOV AL, [DI] ;AN000; Get the last character
439 MOV ZEROED_CHAR, AL ;AN000; Save it.
440 MOV SEP_POSITION, DI ;AN000; Save its position
441 MOV BYTE PTR [DI], 0 ;AN000; Make into a zero
442 END_FOUND2: ;AN031; SEH Handle case of semicolon as last character in path
443 MOV DI, 0 ;AN000; Indicate the string is finished
444 EXIT_ISOLATE: ;AN000;
445 POP ES ;AN000; Restore the registers.
446 POP SI ;AN000;
447 POP CX ;AN000;
448 POP BX ;AN000;
449 POP AX ;AN000;
450 ;
451 RET ;AN000;
452 ;
453 ISOLATE_NEXT_PATH ENDP ;AN000;
454 ;********************************************************************************
455 ; RESTORE_SEPARATOR: Restore the character which separates the characters in
456 ; a path.
457 ;
458 ; INPUT:
459 ; SEP_POSITION - Contain the address of the location to restore the separator.
460 ; ZEROED_CHAR - Contains the character to be restored.
461 ;
462 ; OUTPUT:
463 ; None.
464 ;
465 ;********************************************************************************
466 RESTORE_SEPARATOR PROC NEAR ;AN000;
467 ;
468 PUSH AX ;AN000; Save registers used
469 PUSH SI ;AN000;
470 MOV SI, SEP_POSITION ;AN000; Get the position of the character
471 MOV AL, ZEROED_CHAR ;AN000; Get the character
472 MOV [SI], AL ;AN000; Save character in this position
473 POP SI ;AN000; Restore the registers
474 POP AX ;AN000;
475 RET ;AN000;
476 ;
477 RESTORE_SEPARATOR ENDP ;AN000;
478 ;********************************************************************************
479 ; CHANGE_ATTRIBUTE_ROUTINE: Change the attributes on a group of files.
480 ;
481 ; INPUT:
482 ; SI = The address of a list of files to change the attributes of.
483 ; AX = 0: Attach a new attribute to the file.
484 ; AX = 1: Restore the original attribute to the files.
485 ; BX = The number of files in the list.
486 ;
487 ; OUTPUT:
488 ; If CY = 1, there were error encountered.
489 ; If CY = 0, there were no errors.
490 ;
491 ;********************************************************************************
492 PUBLIC CHANGE_ATTRIBUTE_ROUTINE ;AN000;
493 CHANGE_ATTRIBUTE_ROUTINE PROC FAR ;AN000;
494 ;
495 CALL HOOK_INT_24 ;AN000;
496 ;
497 MOV WAY, AX ;AN000; Save flag indicating whether we are setting or restoring the attrb.
498 MOV NEW_ATTRIB, 02h ;AN000; Set new attribute to hidden.
499 MOV DI, 0 ;AN000; Count of files processed
500 .WHILE < DI B BX > ;AN000;
501 .IF < WAY EQ 0 > ;AN000; Setting the attribute?
502 MOV WORD PTR [SI+12],0 ;AN000; Make filename into a ASCII-Z string
503 MOV DX, SI ;AN000; Load address of filename into DX
504 MOV AX, 4300H ;AN000; Get the file's current attribute
505 DOSCALL ;AN000;
506 .IF < C > ;AN000; Was there an error?
507 JMP CHMOD_ERROR ;AN000; If so, exit the subroutine
508 .ENDIF ;AN000;
509 MOV OLD_ATTRIB, CX ;AN000; Save the attribute
510 MOV CX, NEW_ATTRIB ;AN000; Get the new attribute
511 .ELSE ;AN000; Otherwise, we are restoring the attribute
512 MOV CX, [SI+12] ;AN000; Get the old attribute
513 MOV OLD_ATTRIB, CX ;AN000; Save.
514 MOV WORD PTR [SI+12], 0 ;AN000; Make filename into an ASCII-Z string
515 .ENDIF ;AN000;
516 MOV DX, SI ;AN000; Pointer to the filename
517 MOV AX, 4301H ;AN000; DOS function for setting the attribute
518 DOSCALL ;AN000; Set it.
519 .IF < C > ;AN000; Was there an error?
520 JMP CHMOD_ERROR ;AN000; If so, exit the subroutine
521 .ENDIF ;AN000;
522 MOV CX, OLD_ATTRIB ;AN000; Get the old attribute
523 MOV [SI+12], CX ;AN000; Save in the table
524 ADD SI, 14 ;AN000; Point to the next filename
525 INC DI ;AN000; Increment count of files processed
526 .ENDWHILE ;AN000;
527 CLC ;AN000; Indicate there were no errors
528 RET ;AN000;
529 ;
530 CHMOD_ERROR: ;AN000;
531 STC ;AN000; Indicate there were errors
532 ;
533 CALL RESTORE_INT_24 ;AN000;
534 ;
535 RET ;AN000;
536 ;
537 CHANGE_ATTRIBUTE_ROUTINE ENDP ;AN000;
538 ;****************************************************************************
539 ;
540 ; COMPARE_ROUTINE: Compare two strings.
541 ;
542 ; INPUT:
543 ; SI = The address of the first string. (ASCII-N string)
544 ; DI = The address of the second string. (ASCII-N string)
545 ;
546 ; OUTPUT:
547 ; If CY = 1, the strings do no compare.
548 ; If CY = 0, the strings are the same.
549 ;
550 ; OPERATION:
551 ;
552 ;****************************************************************************
553 PUBLIC COMPARE_ROUTINE ;AN000;
554 COMPARE_ROUTINE PROC FAR ;AN000;
555 ;
556 PUSH ES ;AN000; Make ES = DS
557 PUSH DS ;AN000;
558 POP ES ;AN000;
559 ;
560 MOV CX, [SI] ;AN000; Get the length of the first string
561 .IF < [DI] NE CX > ;AN000; Are the lengths of the strings the same?
562 JMP DO_NOT_COMPARE ;AN000; If not, the strings are not the same
563 .ENDIF ;AN000;
564 ADD SI, 2 ;AN000; Move points past the length words
565 ADD DI, 2 ;AN000;
566 CLD ;AN000; Compare in the forward direction
567 REPZ CMPSB ;AN000; Compare the strings
568 JNZ DO_NOT_COMPARE ;AN000; If the zero flag cleared, strings are not the same
569 CLC ;AN000; Indicate the strings do compare
570 JMP EXIT_COMPARE ;AN000;
571 DO_NOT_COMPARE: ;AN000;
572 STC ;AN000; Indicate the strings do no compare
573 EXIT_COMPARE: ;AN000;
574 POP ES ;AN000;
575 RET ;AN000;
576 ;
577 COMPARE_ROUTINE ENDP ;AN000;
578 ;****************************************************************************
579 ;
580 ; REMOVE_END_BLANKS: Removes the trailing blanks from a string.
581 ;
582 ; INPUT:
583 ; ES:DI Points to the last character in the string.
584 ;
585 ; OUTPUT:
586 ; ES:DI Points to the new end of the string after the blanks have been
587 ; removed.
588 ;
589 ; OPERATION:
590 ;
591 ;****************************************************************************
592 PUBLIC REMOVE_END_BLANKS ;AN000;
593 REMOVE_END_BLANKS PROC FAR ;AN000;
594 ;
595 MOV CX, 0FFFFH ;AN000;
596 MOV AL, ' ' ;AN000;
597 STD ;AN000;
598 REPZ SCASB ;AN000;
599 .IF < NZ > ;AN000;
600 INC DI ;AN000;
601 .ENDIF ;AN000;
602 RET ;AN000;
603 ;
604 REMOVE_END_BLANKS ENDP ;AN000;
605 ;
606 ;****************************************************************************
607 ;
608 ; CHECK_WRITE_ROUTINE Determine if the diskette in drive A is write
609 ; protected.
610 ;
611 ; INPUT:
612 ; CX = 0 - drive A ;AN000;JW
613 ; = 1 - drive B ;AN000;JW
614 ;
615 ; OUTPUT:
616 ; If CY = 1, The disk IS write protected.
617 ; If CY = 0, The disk is NOT write protected.
618 ;
619 ; OPERATION:
620 ;
621 ;****************************************************************************
622 PUBLIC CHECK_WRITE_ROUTINE ;AN000;
623 CHECK_WRITE_ROUTINE PROC FAR ;AN000;
624 ;
625 MOV DRIVE_FLAG,CL ;AN000;
626 ;
627 CALL HOOK_INT_24 ;AN000;
628 ;
629 MOV CHK_W_PROTECT_FLAG, TRUE ;AN000; Indicate to INT 24H handler we are looking for error
630 MOV W_PROTECT_FLAG, FALSE ;AN000; Error has not occured yet.
631 ;
632 MOV W_P_FILENAME_A+3, 0 ;AN000; Make drive string into ASCII-Z string
633 MOV W_P_FILENAME_B+3, 0 ;AN000; Make drive string into ASCII-Z string JW
634 .IF < DRIVE_FLAG eq DRIVE_A > ;AN000;JW
635 MOV DX, OFFSET W_P_FILENAME_A ;AN000; Get address of the string
636 .ELSE ;AN000;JW
637 MOV DX, OFFSET W_P_FILENAME_B ;AN000; Get address of the string JW
638 .ENDIF ;AN000;JW
639 MOV CX, 0 ;AN000; Attribute to give the file
640 MOV INT_24_ERROR, FALSE ;AN000;
641 MOV AH, 5AH ;AN000; DOS Fn. call to create a unique file
642 DOSCALL ;AN000; Create the file
643 .IF < C > ;AN000; Was there an error?
644 .IF < W_PROTECT_FLAG EQ TRUE > ;AN000; If the INT 24H handler was call...
645 JMP WRITE_PROTECTED ;AN000; The disk is write protected.
646 .ELSE ;AN000; Otherwise...
647 JMP CHECK_ERROR ;AN000; There was some other disk error
648 .ENDIF ;AN000;
649 .ELSE ;AN000;
650 .IF < W_PROTECT_FLAG EQ TRUE > ;AN000; If the INT 24H handler was call...
651 JMP WRITE_PROTECTED ;AN000; The disk is write protected.
652 .ENDIF ;AN000;
653 .ENDIF ;AN000; There were no errors...
654 CLOSE_FILE AX ;AN000; Close the created file
655 .IF < DRIVE_FLAG eq DRIVE_A > ;AN000;JW
656 MOV DX, OFFSET W_P_FILENAME_A ;AN000; Get address of the string
657 .ELSE ;AN000;JW
658 MOV DX, OFFSET W_P_FILENAME_B ;AN000; Get address of the string JW
659 .ENDIF ;AN000;JW
660 MOV AH, 41H ;AN000; DOS Fn. for erasing a file
661 DOSCALL ;AN000; Erase the file
662 MOV AX, 0 ;AN000; Indicate the file is NOT write protected
663 CLC ;AN000; Indicate there were no errors
664 JMP CHECK_EXIT ;AN000; Exit the routine
665
666 WRITE_PROTECTED: ;AN000;
667 MOV AX, 1 ;AN000; Indicate the file IS write protected
668 CLC ;AN000; Indicate there were no errors
669 JMP CHECK_EXIT ;AN000;
670
671 CHECK_ERROR: ;AN000;
672 MOV AX, 0 ;AN000; Indicate the file is NOT write protected
673 STC ;AN000; Indicate that there WERE errors
674
675 CHECK_EXIT: ;AN000;
676 CALL RESTORE_INT_24 ;AN000; Restore the original INT 24H handler
677 MOV CHK_W_PROTECT_FLAG, FALSE ;AN000; We are no longer expecting a write protect error
678 RET ;AN000;
679
680 CHECK_WRITE_ROUTINE ENDP ;AN000;
681 ;****************************************************************************
682 ;
683 ; MATCH_FILES_ROUTINE Determine is a list of file exist on a drive.
684 ;
685 ; INPUT:
686 ; DI = Address of the ASCII-N string containing the drive and path to
687 ; search for the files.
688 ; SI = The address of the list of file. If AX = 2, the first two bytes
689 ; in the list are ignored.
690 ; AX = The type of list to use.
691 ; = 1: Use a list with only 12 bytes between the filenames.
692 ; = 2: Use a list with only 14 bytes between the filenames.
693 ; CX = The number of files in the list.
694 ;
695 ; OUTPUT:
696 ; If CY = 1, There was an error access the disk.
697 ; If CY = 0, There were no errors.
698 ; AX = 1: All the files are on the disk.
699 ; AX = 0: All the files are NOT on the disk.
700 ;
701 ; OPERATION:
702 ;
703 ;****************************************************************************
704 PUBLIC MATCH_FILES_ROUTINE ;AN000;
705 MATCH_FILES_ROUTINE PROC FAR ;AN000;
706 ;
707 ;
708 PUSH ES ;AN000; Make ES = DS
709 PUSH DS ;AN000;
710 POP ES ;AN000;
711 ;
712 MOV NUM_FILES, CX ;AN000; Save the number of files
713 MOV LIST_TYPE, AX ;AN000; Save the type of the list
714 ;
715 MOV CX, [DI] ;AN000; Get the length of the string
716 ADD DI, 2 ;AN000; Point SI to the start of the string
717 MOV DX, DI ;AN000; Copy the address of the string
718 ADD DI, CX ;AN000; Point to the end of the string
719 .IF < LIST_TYPE EQ 2 > ;AN000; If this list is a 14 byte list...
720 ADD SI, 2 ;AN000; Bypass the first two bytes in the list
721 .ENDIF ;AN000;
722 MOV STR_PTR, DI ;AN000; Save the pointer to the path string
723 MOV FILE_PTR, SI ;AN000; Save the pointer to the file list
724 MOV BX, 0 ;AN000; Initialize the count of files checked
725 ;
726 .WHILE < BX B NUM_FILES > ;AN000; Perform NUM_FILES interations
727 CLD ;AN000;
728 MOV CX, 12 ;AN000; Move 12 bytes for the filename
729 REP MOVSB ;AN000; Move the filename after the path string
730 MOV BYTE PTR [DI], 0 ;AN000; Make string into an ASCII-Z string
731 MOV AH, 4EH ;AN000; DOS Fn. for find a file
732 MOV CX, 0 ;AN000; Attribute used for search
733 DOSCALL ;AN000; Get the matching filename
734 .IF < C > ;AN000; Was there an error?
735 .IF < AX EQ 18 > ;AN000; If error no = 18, then file not found
736 JMP FILE_NOT_FOUND ;AN000; Return to the user
737 .ELSE ;AN000; Otherwise
738 JMP MATCH_ERROR ;AN000; There was some other type of disk error
739 .ENDIF ;AN000; Exit the subroutine
740 .ENDIF ;AN000;
741 MOV DI, STR_PTR ;AN000; Get the pointer to the string
742 MOV SI, FILE_PTR ;AN000; Get the pointer to the file list
743 .IF < LIST_TYPE EQ 1 > ;AN000; Check list type for incrementing the file pointer
744 ADD SI, 12 ;AN000; 12 bytes between files for list type 1
745 .ELSE ;AN000;
746 ADD SI, 14 ;AN000; 14 bytes between files for list type 2
747 .ENDIF ;AN000;
748 MOV FILE_PTR, SI ;AN000; Save the new file name pointer
749 INC BX ;AN000; Increment the count of files searched for
750 .ENDWHILE ;AN000;
751 CLC ;AN000; Indicate there were no errors
752 MOV AX, 1 ;AN000; Indicate that all the files were found
753 JMP EXIT_MATCH ;AN000;
754 FILE_NOT_FOUND: ;AN000;
755 CLC ;AN000; Indicate that there were no errors
756 MOV AX, 0 ;AN000; But, all the files were not found
757 JMP EXIT_MATCH ;AN000;
758 MATCH_ERROR: ;AN000;
759 STC ;AN000; Indicate that there were errors
760 EXIT_MATCH: ;AN000;
761 POP ES ;AN000;
762 RET ;AN000;
763 ;
764 MATCH_FILES_ROUTINE ENDP ;AN000;
765 ;************************************************************************
766 ;
767 ; CLOSE_FILE_ROUTINE: Close File
768 ;
769 ; INPUT:
770 ; BX = The file handle of the file to close.
771 ;
772 ; OUTPUT:
773 ; CY = 0, AX = undefined, successful
774 ; CY = 1, AX = error code
775 ;
776 ; OPERATION:
777 ;
778 ; THIS MACROS CLOSES THE FILE WITH THE GIVEN FILE HANDLE.
779 ; IT MAKES USE OF INT 21 (AH=3EH).
780 ; IF AN ERROR OCCURS, THE CARRY FLAG IS SET, AND THE ERROR CODE
781 ; IS RETURNED IN AX.
782 ;
783 ;**************************************************************************
784 PUBLIC CLOSE_FILE_ROUTINE ;AN000;
785 CLOSE_FILE_ROUTINE PROC FAR ;AN000;
786 ;
787 ;
788 CALL HOOK_INT_24 ;AN000; Hook in the critical error handler
789 MOV INT_24_ERROR, FALSE ;AN000; Indicate no critical error have occured yet
790 MOV AH, 3EH ;AN000; DOS Fn. for closing a file
791 DOSCALL ;AN000; Close the file
792 CALL RESTORE_INT_24 ;AN000; Restore the old critical error handler
793 RET ;AN000;
794 ;
795 CLOSE_FILE_ROUTINE ENDP ;AN000;
796 ;**************************************************************
797 ;
798 ; CREATE_FILE: Create new File
799 ;
800 ; INPUT:
801 ; DI = The address of the filename in ASCII-N format
802 ; CX = The attribute to give the file
803 ;
804 ; OUTPUT:
805 ; If CY = 0: There were no errors.
806 ; AX - The file handle of the created file.
807 ; If CY = 1: There were file errors. AX contains the error code.
808 ;
809 ; OPERATION:
810 ;
811 ; CREATE_FILE CREATES A FILE WITH THE GIVEN NAME USING INT 21H (AH=5BH)
812 ; IF AN ERROR OCCURS, THE CARRY FLAG IS SET, AND THE ERROR CODE
813 ; IS RETURNED IN AX.
814 ;
815 ;**************************************************************************
816 PUBLIC CREATE_FILE_ROUTINE ;AN000;
817 CREATE_FILE_ROUTINE PROC FAR ;AN000;
818 ;
819 CALL HOOK_INT_24 ;AN000;
820 CALL POS_ZERO ;AN000;
821 MOV DX, DI ;AN000;
822 ADD DX, 2 ;AN000;
823 MOV INT_24_ERROR, FALSE ;AN000;
824 MOV AH,5BH ;AN000;
825 DOSCALL ;AN000;
826 CALL RESTORE_INT_24 ;AN000;
827 RET ;AN000;
828 ;
829 CREATE_FILE_ROUTINE ENDP ;AN000;
830 ;****************************************************************************
831 ;
832 ; ERASE_FILE_ROUTINE: Routine to erase a file.
833 ;
834 ; INPUT:
835 ; DI - The address of an ASCII-N string containing the name of the file
836 ; to erase.
837 ;
838 ; OUTPUT:
839 ; If CY = 0, there were no error encountered.
840 ; If CY = 1, there were errors. AX contains the DOS error code.
841 ;
842 ; OPERATION:
843 ;
844 ; ERASE_FILE ERASES THE FILE USING INT 21H (AH=41H).
845 ; IF AN ERROR OCCURS, THE CARRY FLAG IS SET, AND THE ERROR CODE
846 ; IS RETURNED IN AX.
847 ;
848 ;****************************************************************************
849 PUBLIC ERASE_FILE_ROUTINE ;AN000;
850 ERASE_FILE_ROUTINE PROC FAR ;AN000;
851
852 CALL HOOK_INT_24 ;AN000;
853 CALL POS_ZERO ;AN000;
854 MOV INT_24_ERROR, FALSE ;AN000;
855 MOV DX, DI ;AN000;
856 ADD DX, 2 ;AN000;
857 MOV AH,41H ;AN000;
858 DOSCALL ;AN000;
859 CALL RESTORE_INT_24 ;AN000;
860 RET ;AN000;
861
862 ERASE_FILE_ROUTINE ENDP ;AN000;
863 ;****************************************************************************
864 ;
865 ; CHMOD_FILE_ROUTINE: Change file attributes to read/write
866 ;
867 ; SYNTAX: CHMOD_FILE_ROUTINE
868 ;
869 ; INPUT: DI = POINTER TO ASCII-N STRING - FILE NAME
870 ;
871 ; OUTPUT: None.
872 ;
873 ; OPERATION:
874 ; The CHMOD dos call is executed (43H) to change the file's attributes
875 ; to read/write.
876 ;
877 ;****************************************************************************
878 PUBLIC CHMOD_FILE_ROUTINE ;AN000;
879 CHMOD_FILE_ROUTINE PROC FAR ;AN000;
880
881 CALL HOOK_INT_24 ;AN000;
882 CALL POS_ZERO ;AN000;
883 MOV INT_24_ERROR, FALSE ;AN000;
884 MOV DX, DI ;AN000;
885 ADD DX, 2 ;AN000;
886 MOV AH,043H ;AN000;
887 MOV AL,01 ;AN000;
888 XOR CX,CX ;AN000;
889 DOSCALL ;AN000;
890 CALL RESTORE_INT_24 ;AN000;
891 RET ;AN000;
892
893 CHMOD_FILE_ROUTINE ENDP ;AN000;
894 ;************************************************************************
895 ; FIND_FILE: Find File
896 ;
897 ; INPUT:
898 ; DI - The address of an ASCII-N string contian the name of the file
899 ; to find.
900 ; CX - The attribute to be used in the search.
901 ;
902 ; OUTPUT:
903 ; If CY = 1, there were errors encountered. AX contians the DOS error
904 ; code.
905 ; If CY = 0, there were no errors.
906 ;
907 ; OPERATION:
908 ;
909 ; FINDFILE FINDS THE FIRST FILENAME SPECIFIED USING INT 21 (AH=4EH).
910 ; AND LOADS INFORMATION INTO THE CURRENT DTA.
911 ; NOTE : THE DEFAULT DTA IS AT 80H IN THE PSP.
912 ; IF AN ERROR OCCURS, THE CARRY FLAG IS SET, AND THE ERROR CODE
913 ; IS RETURNED IN AX.
914 ;
915 ;************************************************************************
916 PUBLIC FIND_FILE_ROUTINE ;AN000;
917 FIND_FILE_ROUTINE PROC FAR ;AN000;
918 ;
919 CALL HOOK_INT_24 ;AN000;
920 CALL POS_ZERO ;AN000;
921 MOV DX, DI ;AN000;
922 ADD DX, 2 ;AN000;
923 MOV INT_24_ERROR, FALSE ;AN000;
924 ; CX Contains the attribute to be used in the search
925 MOV AH,4EH ;AN000;
926 DOSCALL ;AN000;
927 CALL RESTORE_INT_24 ;AN000;
928 RET ;AN000;
929
930 FIND_FILE_ROUTINE ENDP ;AN000;
931 ;**************************************************************************
932 ;
933 ; OPEN_FILE_ROUTINE - Open File
934 ;
935 ; INPUT:
936 ; DI - The address of an ASCII-N string containing the name of the
937 ; file to open.
938 ; AL - The mode to open the file with ( 0 = read, 1 = write,
939 ; 2 = read/write)
940 ;
941 ; OUTPUT:
942 ; If CY = 1, there were errors encountered. AX contains the DOS error
943 ; code.
944 ; If CY = 0, there were no errors. AX contains the file handle.
945 ;
946 ; OPERATION:
947 ;
948 ; THIS MACRO OPENS A FILE FOR READ/WRITE OPERATIONS.
949 ; IT MAKES USE OF INT 21 (AH=3DH).
950 ; IF AN ERROR OCCURS, THE CARRY FLAG IS SET, AND THE ERROR CODE
951 ; IS RETURNED IN AX.
952 ;
953 ;**************************************************************************
954 PUBLIC OPEN_FILE_ROUTINE ;AN000;
955 OPEN_FILE_ROUTINE PROC FAR ;AN000;
956 ;
957 CALL HOOK_INT_24 ;AN000;
958 CALL POS_ZERO ;AN000;
959 MOV INT_24_ERROR, FALSE ;AN000;
960 MOV DX, DI ;AN000;
961 ADD DX, 2 ;AN000;
962 ; AL contains the mode for opening the file.
963 MOV AH,3DH ;AN000;
964 DOSCALL ;AN000;
965 CALL RESTORE_INT_24 ;AN000;
966 RET ;AN000;
967
968 OPEN_FILE_ROUTINE ENDP ;AN000;
969 ;**************************************************************************
970 ;
971 ; RENAME_FILE_ROUTINE - Rename File
972 ;
973 ; INPUT:
974 ; SI - The address of an ASCII-N string containing the file to rename
975 ; current file name.
976 ; DI - The address of an ASCII-N string containing the new name for the
977 ; file.
978 ;
979 ; OUTPUT:
980 ; If CY = 1, there were errors encountered. AX contains the DOS error
981 ; error code.
982 ; If CY = 0, there were no errors.
983 ;
984 ;
985 ; OPERATION:
986 ;
987 ; THIS MACRO RENAMES A FILE GIVEN 2 NAMES.
988 ; IT MAKES USE OF INT 21 (AH=56H).
989 ; IF AN ERROR OCCURS, THE CARRY FLAG IS SET, AND THE ERROR CODE
990 ; IS RETURNED IN AX.
991 ;
992 ;**************************************************************************
993 PUBLIC RENAME_FILE_ROUTINE ;AN000;
994 RENAME_FILE_ROUTINE PROC FAR ;AN000;
995
996 CALL HOOK_INT_24 ;AN000;
997 PUSH ES ;AN000;
998 PUSH DS ;AN000;
999 POP ES ;AN000;
1000 PUSH DI ;AN000;
1001 ; SI Contains the address of the string containing the old filename.
1002 MOV DI, SI ;AN000;
1003 CALL POS_ZERO ;AN000;
1004 MOV DX, DI ;AN000;
1005 ADD DX, 2 ;AN000;
1006
1007 POP DI ;AN000;
1008 ; DI contains the address of the string containing the new filename.
1009 CALL POS_ZERO ;AN000;
1010 ADD DI, 2 ;AN000;
1011
1012 MOV INT_24_ERROR, FALSE ;AN000;
1013 MOV AH,56H ;AN000;
1014 DOSCALL ;AN000;
1015 POP ES ;AN000;
1016 CALL RESTORE_INT_24 ;AN000;
1017 RET ;AN000;
1018
1019 RENAME_FILE_ROUTINE ENDP ;AN000;
1020 ;**************************************************************************
1021 ;
1022 ; READ_FILE_ROUTINE: Transfer the specified number of bytes from a file into a
1023 ; buffer location.
1024 ;
1025 ; INPUT:
1026 ; BX - The handle of the file to read.
1027 ; DX - The address of where to store the data
1028 ; CX - The number of characters to read
1029 ;
1030 ; OUTPUT:
1031 ; CY = 0, Read success. AX - number of bytes read
1032 ; CY = 1, Read error. AX contains the error code.
1033 ;
1034 ; OPERATION:
1035 ;
1036 ; THIS MACRO READS TO AN ALREADY OPENED FILE.
1037 ; IT MAKES USE OF INT 21 (AH=3FH).
1038 ; AX WILL RETURN THE NUMBER BYTES ACTUALLY WRITTEN.
1039 ;
1040 ;************************************************************************
1041 PUBLIC READ_FILE_ROUTINE ;AN000;
1042 READ_FILE_ROUTINE PROC FAR ;AN000;
1043 ;
1044 CALL HOOK_INT_24 ;AN000;
1045 MOV INT_24_ERROR, FALSE ;AN000;
1046 ; BX - The file handle
1047 ; CX - The number of bytes to read
1048 ; DX - The address of the buffer to store the data
1049 MOV AH,3FH ;AN000;
1050 DOSCALL ;AN000;
1051 CALL RESTORE_INT_24 ;AN000;
1052 RET ;AN000;
1053
1054 READ_FILE_ROUTINE ENDP ;AN000;
1055 ;**************************************************************************
1056 ;
1057 ; WRITE_FILE_ROUTINE: Transfer the specified number of bytes from a buffer into a
1058 ; specified file.
1059 ;
1060 ; INPUT:
1061 ; BX - The handle of the file to write to.
1062 ; DX - The address of where the data is stored.
1063 ; CX - The number of characters to write.
1064 ;
1065 ; OUTPUT:
1066 ; CY = 0, Write success. AX - number of bytes written.
1067 ; CY = 1, Write error. AX contains the error code.
1068 ;
1069 ; OPERATION:
1070 ;
1071 ; THIS MACRO WRITES TO AN ALREADY OPENED FILE.
1072 ; IT MAKES USE OF INT 21 (AH=3DH).
1073 ; AX WILL RETURN THE NUMBER BYTES ACTUALLY WRITTEN.
1074 ;
1075 ;************************************************************************
1076 PUBLIC WRITE_FILE_ROUTINE ;AN000;
1077 WRITE_FILE_ROUTINE PROC FAR ;AN000;
1078 ;
1079 CALL HOOK_INT_24 ;AN000;
1080 MOV INT_24_ERROR, FALSE ;AN000;
1081 ; BX - The file handle
1082 ; CX - The number of bytes to read
1083 ; DX - The address of the buffer to store the data
1084 MOV AH,40H ;AN000;
1085 DOSCALL ;AN000;
1086 CALL RESTORE_INT_24 ;AN000;
1087 RET ;AN000;
1088
1089 WRITE_FILE_ROUTINE ENDP ;AN000;
1090 ;***************************************************************************
1091 ;
1092 ; CHECK_DISK: Check is the specified fixed disk is present. If disk is
1093 ; present, return disk partition status.
1094 ;
1095 ; INPUT:
1096 ; AX = 1: First fixed disk.
1097 ; = 2: Second fixed disk.
1098 ;
1099 ; OUTPUT:
1100 ; CX = 0: Disk not present.
1101 ; = 1: Disk present - No DOS or EDOS partitions
1102 ; = 2: Disk present - DOS or EDOS partitions exist
1103 ; BX = 01H: Primary DOS partition exists
1104 ; = 02H: Extended DOS partitions exists
1105 ; = 04H: Logical drives exist
1106 ; = 08H: Free space exists in EDOS partition
1107 ; = 10H: Free space exists on disk
1108 ; More than one status bit can be set
1109 ; DX = 0: There is no free space in EDOS partition and the
1110 ; disk.
1111 ; = 1: There is free space in the EDOS partition.
1112 ; = 2: There is no EDOS partition, but there is free
1113 ; disk space.
1114 ; DI = Buffer for fixed disk status information.
1115 ;
1116 ; OPERATION: A call is performed to the FDISK utility (GET_DISK_STATUS)
1117 ; to get the status of the specified fixed disk drive. The returned
1118 ; status information is checked and the memory variables are set as
1119 ; specified above.
1120 ;
1121 ;***************************************************************************
1122 PUBLIC CHECK_DISK_ROUTINE ;AN000;
1123 CHECK_DISK_ROUTINE PROC FAR ;AN000;
1124 ;
1125 PUSH ES ;AN000; Make ES = DS
1126 PUSH DS ;AN000;
1127 POP ES ;AN000;
1128 PUSH DI ;AN000;
1129 ADD DI, 2 ;AN000;
1130 CALL GGET_STATUS ;AN000;
1131 POP DI ;AN000;
1132 MOV [DI+1], CL ;AN000; Store the number of table entries
1133 .IF < ZERO AX > ;AN000;
1134 .IF < BIT BX AND M_DOS_EDOS_PART > ;AN000;
1135 MOV CX, PRESENT_WITH_PART ;AN000;
1136 .ELSE ;AN000;
1137 MOV CX, PRESENT_WITHOUT_PART ;AN000;
1138 .ENDIF ;AN000;
1139 .ELSE ;AN000;
1140 MOV CX, NOT_PRESENT ;AN000;
1141 .ENDIF ;AN000;
1142 MOV DX, NO_EDOS_SPACE ;AN000; Initialize
1143 .IF < BIT BX AND M_EDOS_EXISTS > ;AN000; Does the extended DOS partition exist?
1144 .IF < BIT BX AND M_EDOS_SPACE > ;AN000; Yes! Is there free space in it?
1145 MOV DX, FREE_EDOS_SPACE ;AN000; Indicate that there is free space
1146 .ELSEIF < BIT BX NAND M_FREE_SPACE > ;AN000; Is there no free space on the disk?
1147 MOV DX, NO_EDOS_SPACE ;AN000; Indicate there is no free space in EDOS or on the disk.
1148 .ENDIF ;AN000;
1149 .ELSEIF < BIT BX AND M_FREE_SPACE > ;AN000; No! There is no EDOS partition
1150 MOV DX, NO_EDOS_BUT_SPACE ;AN000; But there is free space on the disk
1151 .ENDIF ;AN000;
1152 POP ES ;AN000;
1153 RET ;AN000;
1154 ;
1155 CHECK_DISK_ROUTINE ENDP ;AN000;
1156 ;************************************************************************;;
1157 ;
1158 ; CHECK_VALID_MEDIA: Check if the diskettes attached will support
1159 ; installation of SELECT. Also, check if install destination will
1160 ; be selected by user or determined by SELECT.
1161 ;
1162 ; SYNTAX: CHECK_VALID_MEDIA var_disk_a, var_disk_b, var_tot, var_disk,
1163 ; var_def, var_index, var_option
1164 ;
1165 ; INPUT:
1166 ; var_disk_a = diskette A presence and type
1167 ; var_disk_b = diskette B presence and type
1168 ; var_tot = total number of dikettes
1169 ; var_disk = 0: first fixed disk is not present
1170 ; > 0: first fixed disk is present
1171 ;
1172 ; OUTPUT:
1173 ; CY = 0: Success variables are returned as defined below.
1174 ; CY = 1: Error - invalid media
1175 ; var_def = 0 use default destination drive
1176 ; = 1 default destination drive not applicable
1177 ; var_index = 1 default destination is drive C
1178 ; = 2 default destination is drive B
1179 ; var_option = 1 possible drive B or C
1180 ; = 2 possible drive A or C
1181 ; = 3 possible drive A or B or C
1182 ; = 4 possible drive A or B
1183 ;
1184 ; OPERATION: The diskette drive types are checked for valid media type.
1185 ; If the diskette media types are valid, a check is made to determine if
1186 ; install destination will be user selected or will be determined by
1187 ; SELECT. The following checks are made.
1188 ;
1189 ; - if one diskette, return valid media and default destination is A
1190 ;
1191 ; - If two diskettes only, return valid and:
1192 ; if A = B, default = B
1193 ; if A <> B, default = A
1194 ; if A and B are mixed 720 and 1.44, destination option is A or B
1195 ;
1196 ; - If one diskette and a fixed disk only, return valid media and
1197 ; destination option is drive A or C.
1198 ;
1199 ; - If two diskettes and a fixed disk, return valid media and:
1200 ; if A = B, destination option is B or C
1201 ; if A <> B, destination option is A or C
1202 ; if A and B are mixed 720 and 1.44, destination option is
1203 ; A or B or C
1204 ;
1205 ;************************************************************************;;
1206 PUBLIC CHECK_VALID_MEDIA_ROUTINE ;AN111;JW
1207 CHECK_VALID_MEDIA_ROUTINE PROC FAR ;AN111;JW
1208
1209
1210 VAR_DISK_A EQU AL ;AN111;JW
1211 VAR_DISK_B EQU BL ;AN111;JW
1212 VAR_DEF EQU CL ;AN111;JW
1213 VAR_INDEX EQU DX ;AN111;JW
1214 VAR_DISK EQU SI ;AN111;JW
1215 VAR_OPTION EQU DI ;AN111;JW
1216
1217 .IF < VAR_DISK_A NE E_DISKETTE_INV > ;AN111; Is disk A present
1218 .IF <VAR_DISK_B NE E_DISKETTE_INV> ;AN111; Is disk B present
1219 .IF < VAR_DISK GT 0 > ;AN111; Hard disk is present?
1220 MOV VAR_DEF, DO_NOT_USE_DEFAULT ;AN111; Yes! Destination drive is undefined
1221 MOV VAR_OPTION,E_OPTION_B_C ;AN111; options will be B or C
1222 MOV VAR_INDEX,DEF_DEST_C ;AN073; SEH highlight option C
1223 CLC ;AN111; Indicate valid media
1224 .ELSE ;AN111;
1225 MOV VAR_DEF, USE_DEFAULT ;AN111; Yes! Use the default destination = B
1226 MOV VAR_INDEX, DEF_DEST_B ;AN111; Drive B is that default
1227 CLC ;AN111; Indicate valid media
1228 .ENDIF ;AN111;
1229 .ELSE ;AN111;
1230 .IF < VAR_DISK GT 0 > ;AN111; Hard disk is present?
1231 MOV VAR_DEF, DO_NOT_USE_DEFAULT ;AN111; Yes! Destination drive is undefined
1232 MOV VAR_OPTION, E_OPTION_A_C ;AN111; options are A or C
1233 MOV VAR_INDEX,DEF_DEST_C ;AN073; SEH highlight option C
1234 CLC ;AN111; Indicate valid media
1235 .ELSE ;AN111;
1236 MOV VAR_DEF, USE_DEFAULT ;AN111; no, Use the default destination
1237 MOV VAR_INDEX, DEF_DEST_A ;AN111; Drive A is that default
1238 CLC ;AN111; Indicate valid media
1239 .ENDIF ;AN111;
1240 .ENDIF ;AN111;
1241 .ELSE ;AN111;
1242 STC ;AN111; Indicate invalid media
1243 .ENDIF ;AN111;
1244 RET ;AN111;
1245
1246 CHECK_VALID_MEDIA_ROUTINE ENDP ;AN111;JW
1247 ;************************************************************************;;
1248 ;
1249 ; SCAN_DISK_TABLE: Scan the specified disk status table from the
1250 ; specified index item for specified field and return status information.
1251 ;
1252 ; INPUT:
1253 ; CX = 1: First fixed disk
1254 ; = 2: Second fixed disk
1255 ; AX = Index of the information to return
1256 ;
1257 ; OUTPUT:
1258 ; AX = 0: Success - Index into table is valid
1259 ; = 1: Error - Index invalid or end of table
1260 ; N_NAME_PART = Partition name.
1261 ; N_SIZE_PART = Partition size.
1262 ; N_STATUS_PART = Partition status
1263 ; P_DRIVE_PART = Drive letter assigned.
1264 ; P_LEVEL1_PART = Version number (1st part). For DOS 4.00 1st part = blank
1265 ; P_LEVEL2_PART = Version number (2nd part). For DOS 4.00 2nd part = 4
1266 ; P_LEVEL3_PART = Version number (3rd part). For DOS 4.00 3rd part = .
1267 ; P_LEVEL4_PART = Version number (4th part). For DOS 4.00 4th part = 0
1268 ;
1269 ; OPERATION:
1270 ; Starts scanning the disk table from the point indicated by var_index
1271 ; for either the name, status or type. The table is scanned until either
1272 ; the desired entry is found, or the end of the table is reached. If
1273 ; the end of the table is reached before a matching entry is found, then
1274 ; var_ret returns 1, else if an entry is found, it returns 0.
1275 ; If found, var_index will also return the index of the entry.
1276 ;
1277 ; Note: The index of the first entry in the table is 1.
1278 ;
1279 ;************************************************************************;;
1280 PUBLIC SCAN_DISK_TABLE_ROUTINE ;AN000;
1281 SCAN_DISK_TABLE_ROUTINE PROC FAR ;AN000;
1282
1283 MOV BX, 0 ;AN000;
1284 .IF < CX EQ TABLE_ONE > ;AN000;
1285 MOV SI, OFFSET DISK_1_START ;AN000; Get the address of the first table
1286 MOV BL, DISK_1_VAL_ITEM ;AN000; Number of entries in the first table
1287 .ELSE ;AN000;
1288 MOV SI, OFFSET DISK_2_START ;AN000; Get the address of the second table
1289 MOV BL, DISK_2_VAL_ITEM ;AN000; Number of entries in the second table
1290 .ENDIF ;AN000;
1291 .IF < AX BE BX > ;AN000;
1292 ; AX contains the index
1293 DEC AX ;AN000; Make the first index a 0
1294 MOV DX, TYPE DISK_STATUS ;AN000; Number of bytes in the structure
1295 MUL DX ;AN000; Calculate the offset into the table
1296 ADD SI, AX ;AN000; Add to the address of the table
1297 COPY_BYTE N_NAME_PART, [SI].N_PART_NAME ;AN000; Copy the table entries
1298 COPY_WORD N_SIZE_PART, [SI].N_PART_SIZE ;AN000;
1299 COPY_BYTE N_STATUS_PART, [SI].N_PART_STATUS ;AN000;
1300 COPY_BYTE P_DRIVE_PART, [SI].P_PART_DRIVE ;AN000;
1301 COPY_BYTE N_TYPE_PART, [SI].N_PART_TYPE ;AN000;
1302 COPY_BYTE N_LEVEL1_PART, [SI].N_PART_LEVEL1 ;AN065;SEH 1st part of version number For DOS 4.00 1st part = blank
1303 COPY_BYTE N_LEVEL2_PART, [SI].N_PART_LEVEL2 ;AN065;SEH 2nd part of version number For DOS 4.00 2nd part = 4
1304 COPY_BYTE N_LEVEL3_PART, [SI].N_PART_LEVEL3 ;AN065;SEH 2nd part of version number For DOS 4.00 3rd part = .
1305 COPY_BYTE N_LEVEL4_PART, [SI].N_PART_LEVEL4 ;AN065;SEH 2nd part of version number For DOS 4.00 4th part = 0
1306 MOV AX, DATA_VALID ;AN000;
1307 .ELSE ;AN000;
1308 MOV AX, DATA_INVALID ;AN000;
1309 .ENDIF ;AN000;
1310 RET ;AN000;
1311
1312 SCAN_DISK_TABLE_ROUTINE ENDP ;AN000;
1313 ;************************************************************************;;
1314 ;
1315 ; UPDATE_DISK_TABLE: Update the specifed disk status table for the
1316 ; specified index item.
1317 ;
1318 ; INPUT:
1319 ; CX = 1: First fixed disk
1320 ; = 2: Second fixed disk
1321 ; AX = Index into table
1322 ;
1323 ; OUTPUT:
1324 ; AX = 0: Success - Index into table is valid
1325 ; = 1: Error - Index into table is not valid
1326 ; partition name = N_NAME_PART
1327 ; partition size = N_SIZE_PART
1328 ; partition status = N_STATUS_PART
1329 ; partition type = N_TYPE_PART
1330 ; drive letter = P_DRIVE_PART
1331 ;
1332 ; OPERATION: If the index into the disk table is valid, the disk table
1333 ; is updated for the specifed index. Disk status information is obtained
1334 ; from pre-defined locations as specified above.
1335 ;
1336 ;************************************************************************;;
1337 PUBLIC UPDATE_DISK_TABLE_ROUTINE ;AN000;
1338 UPDATE_DISK_TABLE_ROUTINE PROC FAR ;AN000;
1339
1340 MOV BH, 0 ;AN000;
1341 .IF < CX EQ TABLE_ONE > ;AN000;
1342 MOV SI, OFFSET DISK_1_START ;AN000; Get the address of the first table
1343 MOV BL, DISK_1_VAL_ITEM ;AN000; Number of entries in the first table
1344 .ELSE ;AN000;
1345 MOV SI, OFFSET DISK_2_START ;AN000; Get the address of the second table
1346 MOV BL, DISK_2_VAL_ITEM ;AN000; Number of entries in the second table
1347 .ENDIF ;AN000;
1348 ; AX contains the index.
1349 DEC AX ;AN000; Make the first index a 0
1350 MOV DX, TYPE DISK_STATUS ;AN000; Number of bytes in the structure
1351 MUL DX ;AN000; Calculate the offset into the table
1352 ADD SI, AX ;AN000; Add to the address of the table
1353 .IF < VAR_INDEX BE BX > ;AN000;
1354 COPY_BYTE [SI].N_PART_NAME, N_NAME_PART ;AN000;
1355 COPY_WORD [SI].N_PART_SIZE, N_SIZE_PART ;AN000;
1356 COPY_BYTE [SI].N_PART_STATUS, N_STATUS_PART ;AN000;
1357 COPY_BYTE [SI].P_PART_DRIVE, P_DRIVE_PART ;AN000;
1358 COPY_BYTE [SI].N_PART_TYPE, N_TYPE_PART ;AN000;
1359 MOV AX, DATA_VALID ;AN000; No error.
1360 .ELSE ;AN000;
1361 MOV AX, DATA_INVALID ;AN000; Indicate an error
1362 .ENDIF ;AN000;
1363 RET ;AN000;
1364 ;
1365 UPDATE_DISK_TABLE_ROUTINE ENDP ;AN000;
1366 ;
1367 CODE_FAR ENDS ;AN000;
1368 ;
1369 END ;AN000;