summaryrefslogtreecommitdiff
path: root/v4.0/src/SELECT/ROUTINE2.ASM
diff options
context:
space:
mode:
authorGravatar Mark Zbikowski2024-04-25 21:24:10 +0100
committerGravatar Microsoft Open Source2024-04-25 22:32:27 +0000
commit2d04cacc5322951f187bb17e017c12920ac8ebe2 (patch)
tree80ee017efa878dfd5344b44249e6a241f2a7f6e2 /v4.0/src/SELECT/ROUTINE2.ASM
parentMerge pull request #430 from jpbaltazar/typoptbr (diff)
downloadms-dos-main.tar.gz
ms-dos-main.tar.xz
ms-dos-main.zip
MZ is back!HEADmain
Diffstat (limited to 'v4.0/src/SELECT/ROUTINE2.ASM')
-rw-r--r--v4.0/src/SELECT/ROUTINE2.ASM1369
1 files changed, 1369 insertions, 0 deletions
diff --git a/v4.0/src/SELECT/ROUTINE2.ASM b/v4.0/src/SELECT/ROUTINE2.ASM
new file mode 100644
index 0000000..2a8b7ad
--- /dev/null
+++ b/v4.0/src/SELECT/ROUTINE2.ASM
@@ -0,0 +1,1369 @@
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;**********************************************************************
12DATA SEGMENT BYTE PUBLIC 'DATA' ;AN000;
13
14PATH_STRING DW 0 ;AN000;
15STRING_SIZE DW 0 ;AN000;
16PATH_PTR DW 0 ;AN000;
17PATH_SIZE DW 0 ;AN000;
18MAX_CHAR DW 0 ;AN000;
19CHAR_COUNT DW 0 ;AN000;
20
21
22SEARCH_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
31INVALID_STRING DB '"/\[]:|<>+=;, ' ;AN000;
32 END_INVALID_STRING EQU $ ;AN000;
33SIZE_INVALID_STR EQU END_INVALID_STRING - INVALID_STRING ;AN000;
34
35ZEROED_CHAR DB 0 ;AN000;
36 DB 0 ;AN000;
37
38SEP_POSITION DW 0 ;AN000;
39NUM_PATHS DW 0 ;AN000;
40
41
42ERR_INVALID_DRV EQU 1 ;AN000;
43ERR_NO_DRIVE EQU 2 ;AN000;
44ERR_DRIVE EQU 3 ;AN000;
45ERR_LEADING_SLASH EQU 4 ;AN000;
46ERR_NO_SLASH EQU 5 ;AN000;
47ERR_LAST_SLASH EQU 6 ;AN000;
48ERR_INVALID_CHAR EQU 7 ;AN000;
49
50OLD_ATTRIB DW 0 ;AN000;
51NEW_ATTRIB DW 0 ;AN000;
52WAY DW 0 ;AN000;
53
54
55
56PUBLIC CHK_W_PROTECT_FLAG ;AN000;
57PUBLIC W_PROTECT_FLAG ;AN000;
58
59W_P_FILENAME_A DB 'A:\',12 DUP(0), 0 ;AC000;JW
60W_P_FILENAME_B DB 'B:\',12 DUP(0), 0 ;AN000;JW
61CHK_W_PROTECT_FLAG DB 0 ;AN000;
62W_PROTECT_FLAG DB 0 ;AN000;
63DRIVE_FLAG DB ? ;AN000;JW
64
65
66NUM_FILES DW 0 ;AN000;
67LIST_TYPE DW 0 ;AN000;
68STR_PTR DW 0 ;AN000;
69FILE_PTR DW 0 ;AN000;
70
71
72
73DATA 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;**********************************************************************
91CODE_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;********************************************************************************
108PUBLIC CHECK_DOS_PATH_ROUTINE ;AN000;
109CHECK_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.
140NO_ERROR_DOS_PATH: ;AN000;
141 CLC ;AN000;
142 JMP EXIT_DOS_PATH ;AN000;
143ERROR_DOS_PATH: ;AN000;
144 STC ;AN000;
145EXIT_DOS_PATH: ;AN000;
146 RET ;AN000;
147 ;
148CHECK_DOS_PATH_ROUTINE ENDP ;AN000;
149 ;
150 ;
151PUBLIC 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;********************************************************************************
182CHECK_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;
249EXIT_NO_ERROR: ;AN000;
250 CLC ;AN000; Indicate there were no errors
251 JMP EXIT_CHECK_PATH ;AN000;
252 ;
253EXIT_CHK_DRV: ;AN000;
254 STC ;AN000; Indicate that there were errors
255EXIT_CHECK_PATH: ;AN000;
256 POP DI ;AN000;
257 RET ;AN000;
258 ;
259 ;
260CHECK_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;********************************************************************************
276CHECK_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 ;
300CHECK_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;********************************************************************************
313CHECK_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 ;
358INVALID_CHAR: ;AN000; Indicate that the name is not valid
359 STC ;AN000;
360CK_V_FILENAME: ;AN000;
361 RET ;AN000;
362 ;
363CHECK_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;********************************************************************************
375VALID_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 ;
397VALID_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;********************************************************************************
414ISOLATE_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
437END_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
442END_FOUND2: ;AN031; SEH Handle case of semicolon as last character in path
443 MOV DI, 0 ;AN000; Indicate the string is finished
444EXIT_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 ;
453ISOLATE_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;********************************************************************************
466RESTORE_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 ;
477RESTORE_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;********************************************************************************
492PUBLIC CHANGE_ATTRIBUTE_ROUTINE ;AN000;
493CHANGE_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 ;
530CHMOD_ERROR: ;AN000;
531 STC ;AN000; Indicate there were errors
532 ;
533 CALL RESTORE_INT_24 ;AN000;
534 ;
535 RET ;AN000;
536 ;
537CHANGE_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;****************************************************************************
553PUBLIC COMPARE_ROUTINE ;AN000;
554COMPARE_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;
571DO_NOT_COMPARE: ;AN000;
572 STC ;AN000; Indicate the strings do no compare
573EXIT_COMPARE: ;AN000;
574 POP ES ;AN000;
575 RET ;AN000;
576 ;
577COMPARE_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;****************************************************************************
592PUBLIC REMOVE_END_BLANKS ;AN000;
593REMOVE_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 ;
604REMOVE_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;****************************************************************************
622PUBLIC CHECK_WRITE_ROUTINE ;AN000;
623CHECK_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
666WRITE_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
671CHECK_ERROR: ;AN000;
672 MOV AX, 0 ;AN000; Indicate the file is NOT write protected
673 STC ;AN000; Indicate that there WERE errors
674
675CHECK_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
680CHECK_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;****************************************************************************
704PUBLIC MATCH_FILES_ROUTINE ;AN000;
705MATCH_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;
754FILE_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;
758MATCH_ERROR: ;AN000;
759 STC ;AN000; Indicate that there were errors
760EXIT_MATCH: ;AN000;
761 POP ES ;AN000;
762 RET ;AN000;
763 ;
764MATCH_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;**************************************************************************
784PUBLIC CLOSE_FILE_ROUTINE ;AN000;
785CLOSE_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 ;
795CLOSE_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;**************************************************************************
816PUBLIC CREATE_FILE_ROUTINE ;AN000;
817CREATE_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 ;
829CREATE_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;****************************************************************************
849PUBLIC ERASE_FILE_ROUTINE ;AN000;
850ERASE_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
862ERASE_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;****************************************************************************
878PUBLIC CHMOD_FILE_ROUTINE ;AN000;
879CHMOD_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
893CHMOD_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;************************************************************************
916PUBLIC FIND_FILE_ROUTINE ;AN000;
917FIND_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
930FIND_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;**************************************************************************
954PUBLIC OPEN_FILE_ROUTINE ;AN000;
955OPEN_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
968OPEN_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;**************************************************************************
993PUBLIC RENAME_FILE_ROUTINE ;AN000;
994RENAME_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
1019RENAME_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;************************************************************************
1041PUBLIC READ_FILE_ROUTINE ;AN000;
1042READ_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
1054READ_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;************************************************************************
1076PUBLIC WRITE_FILE_ROUTINE ;AN000;
1077WRITE_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
1089WRITE_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;***************************************************************************
1122PUBLIC CHECK_DISK_ROUTINE ;AN000;
1123CHECK_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 ;
1155CHECK_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;************************************************************************;;
1206PUBLIC CHECK_VALID_MEDIA_ROUTINE ;AN111;JW
1207CHECK_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
1246CHECK_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;************************************************************************;;
1280PUBLIC SCAN_DISK_TABLE_ROUTINE ;AN000;
1281SCAN_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
1312SCAN_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;************************************************************************;;
1337PUBLIC UPDATE_DISK_TABLE_ROUTINE ;AN000;
1338UPDATE_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 ;
1365UPDATE_DISK_TABLE_ROUTINE ENDP ;AN000;
1366 ;
1367CODE_FAR ENDS ;AN000;
1368 ;
1369END ;AN000;