1 ;***************************************************************************
2 ; Subroutines which are called by the macros in MACROS.INC.
5 ; This is a stand alone module and is meant to be linked with the calling
8 ;***************************************************************************
10 INCLUDE MAC_EQU
.INC ;AN000;
11 INCLUDE PAN
-LIST
.INC ;AN000;
12 INCLUDE PANEL
.MAC
;AN000;
14 ;**********************************************************************
15 DATA SEGMENT BYTE PUBLIC 'DATA' ;AN000;
18 NULl_DEVICE
DB 'nul',0 ;AN000;
19 CON_DEVICE
DB 'con',0 ;AN000;
21 SUB_PROGRAM
DB 0 ;AN000;
22 PUBLIC EXEC_ERR
;AN000;
24 FIRST_TRY
DB 0 ;AN000;DT
25 INT24_STATUS
DB 0 ;AN000;
26 UNHOOKED EQU
0 ;AN000;
28 PUBLIC EXEC_DEALLOC
,EXEC_FDISK
;AN000;
29 EXEC_DEALLOC
DB 0 ;AN000;DT
30 EXEC_FDISK
DB 0 ;AN000;DT
31 EXEC_DEHELP
DB 0 ;AN000;DT
33 DATA ENDS
;AN000; DATA
34 ;**********************************************************************
37 INCLUDE STRUC.INC ;AN000;
38 INCLUDE MACROS
.INC ;AN000;
39 INCLUDE VARSTRUC
.INC ;AN000;
40 INCLUDE EXT
.INC ;AN000;
41 EXTRN EXIT_DOS
:FAR ;AN000;
42 EXTRN SYSDISPMSG
:FAR ;AN000;
43 EXTRN HANDLE_ERROR_CALL
:FAR ;AN000;
44 EXTRN ALLOCATE_MEMORY_CALL
:FAR ;AN000;
45 EXTRN DEALLOCATE_MEMORY_CALL
:FAR ;AN000;
47 EXTRN INT_23_VECTOR
:NEAR ;AN074;SEH ctrl-break
48 EXTRN INT_24_VECTOR
:NEAR ;AN000;
49 EXTRN INT_2F_VECTOR
:NEAR ;AN000;
50 EXTRN INT_2F_256KB
:NEAR ;AN000;
51 EXTRN INT_2F_FORMAT
:NEAR ;AN111;JW
52 EXTRN ALLOCATE_HELP
:FAR ;AN000;
53 EXTRN DEALLOCATE_HELP
:FAR ;AN000;
56 ;**********************************************************************
57 CODE_FAR
SEGMENT PARA
PUBLIC 'CODE' ;AN000; Segment for far routine
58 ASSUME
CS:CODE_FAR
,DS:DATA ;AN000;
60 ;************************************************************************
62 ; APPEND_STRING: Append an ASCII-N string to the specified string.
65 ; SI - OFFSET NAME_SRC
67 ; DI - OFFSET NAME_DEST
75 ;****************************************************************************
76 PUBLIC APPEND_STRING_ROUTINE
;AN000;
77 APPEND_STRING_ROUTINE PROC
FAR ;AN000;
81 POP ES ;AN000; ES and DS point to the data segment
83 .IF < CX LT
<WORD PTR [DI]> > ;AN000;
86 SUB CX, [DI] ;AN000; Calculate space for the other string
87 .IF < CX GE
<WORD PTR [SI]>> ;AN000;
88 MOV CX, [SI] ;AN000; Move the entire string
90 MOV AX, [DI] ;AN000; Current size of destination string
91 ADD [DI], CX ;AN000; Add in the length of the new string
92 ADD DI, AX ;AN000; Add length of string to pointer
93 ADD DI, 2 ;AN000; Increment to pass first word and last byte
94 ADD SI, 2 ;AN000; Point source to start of the string
103 APPEND_STRING_ROUTINE ENDP
;AN000;
104 ;************************************************************************
106 ; COPY_ROUTINE - Subroutine to perform the copy string operation.
109 ; SI - OFFSET NAME_SRC
111 ; DI - OFFSET NAME_DEST
116 ; OPERATION: Copies NAME_SRC1 to NAME_DEST. If NAME_SRC1 is longer then
117 ; IMMED_MAX, then only IMMED_MAX bytes are copied.
119 ;****************************************************************************
120 PUBLIC COPY_ROUTINE
;AN000;
121 COPY_ROUTINE PROC
FAR ;AN000;
125 POP ES ;AN000; ES and DS point to the data segment
127 PUSH DI ;AN000; Save OFFSET NAME_DEST
128 MOV DX, AX ;AN000; Save IMMED_MAX
129 CLD ;AN000; Move strings in the forward direction
130 MOV CX,WORD PTR [SI] ;AN000; Get length of source string
131 ADD SI,2 ;AN000; Point SI to start of string
132 ADD DI,2 ;AN000; Point DI to start of destination.
133 .IF < CX GT
AX > ;AN000;
134 MOV CX,AX ;AN000; Will not fit so adjust length
136 SUB AX,CX ;AN000; Amount of room left.
137 REP MOVSB ;AN000; Move the string
138 SUB DX,AX ;AN000; Subtract the amount left over
140 MOV WORD PTR [SI],DX ;AN000; Store the length of the string
145 COPY_ROUTINE ENDP
;AN000;
146 ;******************************************************************************
148 ; PUSH_ROUTINE: Routine to do the actual pushing of the screen label
151 ; AX - Contains the address of the code for this screen
156 ; OPERATION: The screen label address is pushed onto the SELECT stack
157 ; provided the numher of entries on the stack will not exceed the
158 ; maximum. Error will NOT be generated if the function was not
161 ;******************************************************************************
162 PUBLIC PUSH_ROUTINE
;AN000;
163 PUSH_ROUTINE PROC
FAR ;AN000;
165 .IF < STACK_INDEX B STACK_SIZE
> ;AN000; Is there any room?
166 MOV BL,STACK_INDEX
;AN000; Get the index
168 MOV SELECT_STACK
[BX],AX ;AN000; Store the label
169 ADD STACK_INDEX
,2 ;AN000; Point to next free space
172 PUSH_ROUTINE ENDP
;AN000;
173 ;******************************************************************************
175 ; POP_ROUTINE: Routine to do the actual poping of the screen label
181 ; SI contains the address of the screen code.
183 ; OPERATION: The screen label address is poped from the SELECT stack
184 ; provided there are entries on the stack. If there are no values
185 ; on the stack then the address of the EXIT_DOS screen will be
188 ;******************************************************************************
189 PUBLIC POP_ROUTINE
;AN000;
190 POP_ROUTINE PROC
FAR ;AN000;
192 .IF < STACK_INDEX A
0 > ;AN000; Is there anything on the stack?
193 SUB STACK_INDEX
,2 ;AN000; Point to last item on the stack
194 MOV BL,STACK_INDEX
;AN000; Get the index
196 MOV SI,SELECT_STACK
[BX] ;AN000; Get the label
198 MOV SI,OFFSET EXIT_DOS
;AN000; EXIT_DOS screen
202 POP_ROUTINE ENDP
;AN000;
203 ;************************************************************************
205 ; MAKE_DIR_PATHS_ROUTINE: Create the specified directory including all
206 ; the specified sub-directories if they do not exist.
209 ; BX - Points to an ASCII-N string containing the path to create
213 ; CY = 1 Error - AX will contain an error code.
215 ; OPERATION: The directory pathname is created.
216 ; If the drive letter and colon are not followed by a '\', then the
217 ; macro will start creating the directories from the default directory.
218 ; If they are followed by a '\', then the macro will start at the root.
219 ; If an error occures, then sub-directories which have been created will
223 ;****************************************************************************
224 PUBLIC MAKE_DIR_PATHS_ROUTINE
;AN000;
225 MAKE_DIR_PATHS_ROUTINE PROC
FAR ;AN000;
232 MOV AH, 1 ;AN000; Flag indicating adding or deleting dirs
233 MOV SI, 0 ;AN000; End of the first path created
234 MOV DI, BX ;AN000; Offset of the ASCII-N string
235 ADD DI, 5 ;AN000; Point to the beginning of the path
236 MOV DX, WORD PTR [BX] ;AN000; Get the length of the string
237 MOV CX, DX ;AN000; Store in another variable as well
238 SUB CX, 3 ;AN000; Skip the first 3 characters 'C:\'
239 MOV AL, '\' ;AN000; Delimiter to search for
240 CLD ;AN000; Start searching in the forward direction
243 PROCESS_NEXT_DIR: ;AN000;
244 CMP AH, 1 ;AN000; Adding or deleting directories?
245 JNE DELETING_DIR_1 ;AN000; If adding, then jump
246 CMP CX,0 ;AN000; Is the string length zero?
247 JNE LENGTH_NOT_ZERO ;AN000;
248 JMP NORMAL_EXIT ;AN000;
249 DELETING_DIR_1: ;AN000;
250 CMP SI, DI ;AN000; Was this the first DIR created?
251 JNE LENGTH_NOT_ZERO ;AN000;
252 JMP ERROR_EXIT ;AN000;
254 LENGTH_NOT_ZERO: ;AN000;
256 JNZ STRING_END ;AN000; If not zero, we reached the string end
258 INC CX ;AN000; By adjusting DI, more bytes to the strings end
259 CMP AH,1 ;AN000; Adding or deleting
260 JNE DELETING_DIR_2 ;AN000;
261 DEC DI ;AN000; Back DI up to point to the '\'
263 MOV WORD PTR [BX], DX ;AN000; Length of entire string
264 SUB WORD PTR [BX], CX ;AN000; Subtract the amount left in string
265 JMP ADJUST_DONE
;AN000;
266 DELETING_DIR_2: ;AN000;
267 INC DI ;AN000; Adjust DI to point to the '\'
268 MOV WORD PTR [BX], CX ;AN000; Length left in string
271 CMP AH, 1 ;AN000; Adding or deleting directories
272 JNE DELETING_DIR_3
;AN000;
273 CMP SI, 0 ;AN000; Created a DIR yet?
274 JNE MAKE_START
;AN000;
276 ;**********************************************************************
277 PUSHH
<DX,DI> ;AN000;
279 MOV DI,BX ;AN000; Get the offset of the string
280 CALL FAR PTR POS_ZERO
;AN000; Make into an ASCII-Z string
281 MOV INT_24_ERROR
, 0 ;AN000; Zero the number of critical errors
282 MOV DX,BX ;AN000; Get the start of the string
284 MOV AH,3
BH ;AN000; DOS function call number
288 ;**********************************************************************
294 ;**********************************************************************
295 PUSHH
<DX,DI> ;AN000;
297 CALL FAR PTR POS_ZERO
;AN000; position the '0' at the end of the path
298 MOV INT_24_ERROR
, 0 ;AN000; Zero the number of critical errors
299 MOV DX,BX ;AN000; advance pointer to beginning of path
301 MOV AH,39H
;AN000; make directory interrupt
302 DOSCALL
;AN000; call to DOS interrupt 21
304 ;**********************************************************************
305 JC CANNOT_MAKE
;AN000;
309 POP CX ;AN000; Pop the previously saved AX value
310 PUSH AX ;AN000; Push the make dir error message
312 STD ;AN000; Now search in the backward direction
313 MOV CX, WORD PTR [BX] ;AN000;
315 DELETING_DIR_3: ;AN000;
317 ;**********************************************************************
318 PUSHH <DX,DI> ;AN000;
320 CALL FAR PTR POS_ZERO ;AN000; position the '0' at the end of the path
321 MOV INT_24_ERROR, 0 ;AN000; Zero the number of critical errors
322 MOV DX,BX ;AN000; advance pointer to beginning of path
324 MOV AH,3AH ;AN000; remove the specified directory
325 DOSCALL ;AN000; call to DOS interrupt 21
327 ;**********************************************************************
328 JC ERROR_POP_EXIT ;AN000;
331 MOV BYTE PTR [DI], '\' ;AN000; Put the delimiter back
333 JE NORMAL_EXIT
;AN000; If CX = 0, string ends
336 JNE DELETING_DIR_4
;AN000;
338 JMP PROCESS_NEXT_DIR
;AN000;
339 DELETING_DIR_4: ;AN000;
341 JMP PROCESS_NEXT_DIR
;AN000;
343 ERROR_POP_EXIT: ;AN000;
344 POP CX ;AN000; Pop the extra value off the stack.
346 POP AX ;AN000; Pop the error message number
348 JMP PATHS_DONE
;AN000;
353 MOV WORD PTR [BX], DX ;AN000; Restore the original path length
359 MAKE_DIR_PATHS_ROUTINE ENDP
;AN000;
360 ;************************************************************************
362 ; POS_ZERO - Position a zero at the end of an ASCII-N string, making it
363 ; into an ASCII-Z string.
366 ; DI - Points to the string to covert.
371 ; OPERATION: An ASCII-N string is converted to an ASCII-Z string.
373 ;****************************************************************************
374 PUBLIC POS_ZERO
;AN000;
375 POS_ZERO PROC
FAR ;AN000;
380 MOV AX,[DI] ;AN000; Get the length of the string
381 ADD DI,AX ;AN000; Add the length to the offset
382 ADD DI,2 ;AN000; Adjust for the length word
383 MOV BYTE PTR [DI],0 ;AN000; Position the zero after the end.
390 POS_ZERO ENDP
;AN000;
391 ;************************************************************************
393 ; BEEP_ROUTINE - Cause the speaker to create a tone of a given frequency
397 ; DI - The frequency of the tone to create.
398 ; BX - The duration of the tone.
403 ; OPERATION: Causes the speaker to produce a tone.
405 ;****************************************************************************
406 PUBLIC BEEP_ROUTINE
;AN000;
407 BEEP_ROUTINE PROC
FAR ;AN000;
409 MOV AL,0B6H ;AN000; write timer mode register
411 MOV DX,14H
;AN000; timer divisor=
412 MOV AX,4F38H
;AN000; 1331000/frequency
414 OUT 42H
,AL ;AN000; write timer 2 count low byte
416 OUT 42H
,AL ;AN000; write timer 2 count high byte
417 IN AL,61H
;AN000; get current PORT B setting
418 MOV AH,AL ;AN000; and save it in AH
419 OR AL,3 ;AN000; turn on speaker
421 B_WAIT: MOV CX,2801 ;AN000; wait 10 milliseconds
422 SPKR_ON:LOOP SPKR_ON
;AN000;
424 JNZ B_WAIT
;AN000; beep until finished
425 MOV AL,AH ;AN000; recover value of port
429 BEEP_ROUTINE ENDP
;AN000;
430 ;************************************************************************
432 ; BIN_TO_CHAR_ROUTINE: Convert a binary number to ASCII format.
435 ; AX - The binary number to convert.
436 ; DI - Pointer to the ASCII-N string to store the result.
441 ; OPERATION: The specified 16 bit numeric variable contents are
442 ; converted to ASCII and stored in ASCII-N format. Leading zeros
443 ; will not be stored.
445 ;****************************************************************************
446 PUBLIC BIN_TO_CHAR_ROUTINE
;AN000;
447 BIN_TO_CHAR_ROUTINE PROC
FAR ;AN000;
449 MOV SI, DI ;AN000; Copy the string pointer
450 ADD SI, 6 ;AN000; Point to the string END
451 MOV CX, 10 ;AN000; Number to divide AX by
453 .WHILE < NONZERO
AX> ;AN000;
454 MOV DX, 0 ;AN000; Zero the high order word
455 DIV CX ;AN000; Divide the binary number
456 ADD DL, 48 ;AN000; Convert to ASCII
457 MOV [SI], DL ;AN000; Store in the string.
458 DEC SI ;AN000; Point to the next free string space
460 SUB SI, DI ;AN000; Get the difference in the pointers
461 DEC SI ;AN000; Adjust for the lenght word
462 MOV WORD PTR [DI], 5 ;AN000; Store the number of characters
463 SUB WORD PTR [DI], SI ;AN000; Subtract the number of extra digits
464 MOV CX, WORD PTR [DI] ;AN000;
467 .WHILE < NONZERO
CX > ;AN000;
468 COPY_BYTE
[BX],[BX+SI] ;AN000;
474 BIN_TO_CHAR_ROUTINE ENDP
;AN000;
475 ;**************************************************************************
477 ; PREPARE_FILE_ROUTINE: Prepare a file and a buffer for the construction
478 ; of that file line by line.
481 ; BX = The address of an ASCII-N string containing the name of the file
484 ; OUTPUT: CY = 0: No error was encountered.
485 ; CY = 1: There was an error encountered.
487 ; OPERATION: A attempt is made to create the file. If it fails because
488 ; the file already exists, then the file is opened for writing.
489 ; The user will then write to the file be calling WRITE_LINE macro. The
490 ; data will be temperarily stored in a buffer to limit the actual number
491 ; of writes to the file.
493 ;**************************************************************************
494 PUBLIC PREPARE_FILE_ROUTINE
;AN000;
495 PREPARE_FILE_ROUTINE PROC
FAR ;AN000;
497 ;**********************************************************************
498 ; Try to create the file
499 ;**********************************************************************
500 MOV DI, BX ;AN000; Get the address of the file name string
501 CALL POS_ZERO
;AN000; Make the ASCII-N string into an ASCII-Z
502 MOV DX, DI ;AN000; Get the address again
503 ADD DX, 2 ;AN000; Pass the length word and point to string
504 MOV N_WRITE_ERR_CODE
, 0 ;AN000; Indicate there have been no errors yet
505 MOV INT_24_ERROR
, 0 ;AN000; Zero the number of critical errors
506 MOV CX, 0 ;AN000; Attributes to give the file
507 MOV AH, 3
CH ;AN000; Function for creating a file
508 DOSCALL
;AN000; Create the file
509 ;**********************************************************************
510 ; See if an error has occured.
511 ;**********************************************************************
512 .IF < C
> ;AN000; Did the DOS fn. return an error?
513 .IF < AX EQ 5 > ;AN000; Was the error ACCESS DENIED?
514 MOV DX, BX ;AN000; Get the address of the string
515 MOV INT_24_ERROR
, 0 ;AN000; Zero the number of critical errors
516 MOV AX, 3D01H
;AN000; DOS Fn. for opening a file
518 .IF < C
> ;AN000; Was there an error?
519 MOV N_WRITE_ERR_CODE
, AX ;AN000; Save this error code
522 MOV N_WRITE_ERR_CODE
, AX ;AN000;
526 .IF < N_WRITE_ERR_CODE NE
0 > ;AN000;
529 MOV N_WRITE_HANDLE
, AX ;AN000;
533 END_PREPARE_FILE: ;AN000;
537 PREPARE_FILE_ROUTINE ENDP
;AN000;
538 ;**************************************************************************
540 ; WRITE_LINE_ROUTINE: Write a line to the file being constructed.
543 ; BX = The address of an ASCII-N string containing the line to write
546 ; OUTPUT: CY = 0: No error was encountered.
547 ; CY = 1: An error was encountered.
549 ; OPERATION: The line that is passed, has a CR and a LF appended to the
550 ; end of the line. The data is then stored in a buffer. When the
551 ; buffer is full, the data is written to the disk.
553 ;**************************************************************************
554 PUBLIC WRITE_LINE_ROUTINE
;AN000;
555 WRITE_LINE_ROUTINE PROC
FAR ;AN000;
558 ; See if there has been an error so far ;
559 .IF < N_WRITE_ERR_CODE
EQ 0 > ;AN000; Has there been an error?
560 MOV SI, BX ;AN000; No! Get the string address
561 ADD SI, WORD PTR [BX] ;AN000; Get the end of string address
562 ADD SI, 2 ;AN000; Adjust for the length word
563 MOV BYTE PTR [SI], E_CR
;AN000; Append a carrage return to the string
564 MOV BYTE PTR [SI+1], E_LF
;AN000; Append a line feed to the string
565 MOV CX, WORD PTR [BX] ;AN000; Get the length of the string
566 ADD CX, 2 ;AN000; Increase the string length by two
567 MOV DX, BX ;AN000; Get the address of the string
568 ADD DX, 2 ;AN000; Adjust pointer for length word
569 MOV BX, N_WRITE_HANDLE
;AN000; Handle for the already opened file
570 MOV INT_24_ERROR
, 0 ;AN000; Zero the number of critical errors
571 MOV AH, 40H
;AN000; Function call for writing to a file
572 DOSCALL
;AN000; Write the line
573 .IF < C
> ;AN000; Was there an error?
574 MOV N_WRITE_ERR_CODE
, AX ;AN000; Yes! Save the error code
579 WRITE_LINE_ROUTINE ENDP
;AN000;
580 ;**************************************************************************
582 ; SAVE_FILE_ROUTINE: Empty the data in the buffer being used to create
583 ; the file and then close the file.
586 ; BX - The address of the string containing the file name.
588 ; OUTPUT: CY = 0: No error was encountered.
589 ; CY = 1: An error was encountered.
590 ; AX will contain the code of the error which occured.
592 ; OPERATION: The routine will check to see if there is any data left in
593 ; the buffer. If there is, the data is written to the file being
594 ; created. The file is then closed. If errors were encountered at
595 ; anytime during the create process, then the carry flag will be set
596 ; and the error code will be returned in AX.
598 ;**************************************************************************
599 PUBLIC SAVE_FILE_ROUTINE
;AN000;
600 SAVE_FILE_ROUTINE PROC
FAR ;AN000;
602 .IF < N_WRITE_ERR_CODE NE
0 > ;AN000; Has an error been encountered?
603 MOV DI, BX ;AN000; Yes! Erase the file.
604 CALL POS_ZERO
;AN000; Make string into an ASCII-Z string
605 MOV INT_24_ERROR
, 0 ;AN000; Zero the number of critical errors
606 MOV DX, DI ;AN000; Get the address of the string
607 ADD DX, 2 ;AN000; Advance pointer past length word
608 MOV AH, 41H
;AN000; DOS function for erasing a file
609 DOSCALL
;AN000; Erase the file
610 .ELSE ;AN000; Otherwise, if no error.
611 MOV BX, N_WRITE_HANDLE
;AN000; Get the file handle
612 MOV INT_24_ERROR
, 0 ;AN000; Zero the number of critical errors
613 MOV AH, 3EH
;AN000; DOS function for closing a file
614 DOSCALL
;AN000; Close the file
615 .IF < C
> ;AN000; Error closing the file?
616 MOV N_WRITE_ERR_CODE
, AX ;AN000; Yes! Save the error code
620 MOV AX, N_WRITE_ERR_CODE
;AN000; Return the error code
621 .IF < N_WRITE_ERR_CODE NE
0 > ;AN000; Have errors been encountered?
622 STC ;AN000; Yes! Set the carry flag
624 CLC ;AN000; Clear the carry flag
629 SAVE_FILE_ROUTINE ENDP
;AN000;
630 ;****************************************************************************
632 ; EXEC_PROGRAM_ROUTINE: Loads another program into memory and begins
635 ; INPUT: child = Name of the program to execute (ASCII-N format)
636 ; name_com = The command line to be passed to parm_block
637 ; parm_block = Parameter block for child program.
638 ; re_dir = Flag indicating whether to redirect the output or not.
639 ; = 1: Redirect the output.
640 ; = 0: Don't redirect the output.
642 ; OUTPUT: CY = 0: Successful
643 ; CY = 1: Error - AX has the error code.
645 ; OPERATION: The command line to be passed to the parameter block is
646 ; copied to the command buffer specified for the parameter block and
647 ; a carrage return is appended to the end of the buffer. (The
648 ; command line length can be zero.
650 ; The segment offsets in the parameter block are defined and DOS
651 ; function call 29H is performed to set up the default FCB's.
653 ; DOS function call 4Bh is performed to load and execute the
654 ; specified child program. The contents of SS and SP are destroyed
655 ; during the call, so they must be save and restored later. When the
656 ; parent program (SELECT) gets control, all available memory is
657 ; allocated to it. It is assumed that memory has been freed (Function
658 ; call 4Ah - FREE_MEM) before invoking this function.
660 ;************************************************************************
662 PUBLIC EXEC_PROGRAM_ROUTINE
;AN000;
663 EXEC_PROGRAM_ROUTINE PROC
FAR ;AN000;
666 EX_CHILD EQU
[BP]+12 ;AN000; Equates for temporary variables
667 EX_NAME_COM EQU
[BP]+10 ;AN000;
668 EX_PARM_BLOCK EQU
[BP]+8 ;AN000;
669 EX_RE_DIR EQU
[BP]+6 ;AN000;
671 MOV SUB_PROGRAM
, TRUE
;AN000;
673 PUSH BP ;AN000; Save base pointer
674 MOV BP, SP ;AN000; Set up pointer for temp. variables
676 PUSH DS ;AN000; Save the segment registers
680 DOSCALL
;AC000;JW get DTA address
681 PUSH ES ;AC000;JW save DTA seg
682 PUSH BX ;AC000;JW save DTA off
685 POP ES ;AN000; Point ES to the current data segment
687 .IF < <WORD PTR EX_RE_DIR
> EQ EXEC_DIR
> ;AN000;
688 MOV AH, 3EH
;AN000; Close Stdout
689 MOV BX, STDOUT
;AN000;
691 MOV DX, OFFSET NULL_DEVICE
;AN000; Open the NULL device
692 MOV AX, 3D01H
;AN000;
694 MOV AH, 3EH
;AN000; Close Stderr
695 MOV BX, STDERR
;AN000;
697 MOV DX, OFFSET NULL_DEVICE
;AN000; Open the NULL device
698 MOV AX, 3D01H
;AN000;
703 MOV SI, EX_NAME_COM
;AN000; Get the address of the command line
704 MOV CX, WORD PTR [SI] ;AN000; Get the length of the command line
705 MOV BYTE PTR CMD_BUFF
, CL ;AN000; Store the lenth of the string
706 MOV DI, OFFSET CMD_BUFF
+1 ;AN000; Location to place the string
707 ADD SI, 2 ;AN000; Adjust pointer for length word
708 CLD ;AN000; Move in the forward direction
709 REP MOVSB ;AN000; Copy the string
710 MOV BYTE PTR [DI], 0DH ;AN000; Place a carriage return at the end.
712 MOV DI, EX_CHILD
;AN000; Get the address of the program name string
713 CALL POS_ZERO
;AN000; Turn into an ASCII-Z string
714 MOV SI,EX_PARM_BLOCK
;AN000; Address of the parameters
715 MOV AH,62H
;AN000; DOS Function number for getting the PSP segment
716 DOSCALL
;AN000; Get the current PSP segment
718 MOV [SI]+8, BX ;AN000; Store PSP segment in the parm block
719 MOV [SI]+12, BX ;AN000; These are the FCB segments
720 MOV AX, DATA ;AN000; Get the address of the data segment
721 MOV [SI]+4, AX ;AN000; Segment of the command line
723 MOV ES, BX ;AN000; ES:DI points to the FCB to load
724 MOV DI, 5
CH ;AN000; First FCB to load
725 MOV BX, SI ;AN000; Move the address of the parm block
726 MOV SI, [BX]+2 ;AN000; Get the address of the command line
727 INC SI ;AN000; Skip the length byte
728 MOV AX, 2900H
;AN000; DOS Function for parsing a command line
729 DOSCALL
;AN000; Parse the command line
730 MOV AX, 2900H
;AN000;
731 MOV DI, 6
CH ;AN000; ES:DI points to the second FCB
732 DOSCALL
;AN000; Parse the second filename
734 ;INT 4BH DESTROYS SS,SP ;
735 MOV WORD PTR SAVE_AREA
, SP ;AN000; Save the stack segment and pointer
736 MOV WORD PTR SAVE_AREA
[2], SS ;AN000;
738 MOV FIRST_TRY
,TRUE
;AN000;DT initialize variables
739 MOV EXEC_DEALLOC
,FALSE
;AN000;DT
740 MOV EXEC_DEHELP
,FALSE
;AN000;DT
742 MOV INT_24_ERROR
, 0 ;AN000; Zero the number of critical errors
743 PUSH DS ;AN000; Save the current data segment
744 POP ES ;AN000; Point ES to the current data segment
745 MOV DX, EX_CHILD
;AN000; Get the string with the name of the sub-program
746 ADD DX, 2 ;AN000; Adjust pointer passed length word
747 MOV AX,4B00H
;AN000; DOS Function number of executing a sub-program
749 DOSCALL
;AN000; Fork to the sub-process
752 MOV EXEC_ERR
,TRUE
;AN000;DT
754 MOV EXEC_ERR
,FALSE
;AN000;DT
757 MOV AX,DATA ;AN000; Restore the data register first
758 MOV DS,AX ;AN000; Load the data segment register
760 CLI ;AN000; Turn off interrupts while setting SS
761 MOV SS,WORD PTR SAVE_AREA
[2] ;AN000; Restore the stack segment and pointer
762 MOV SP,WORD PTR SAVE_AREA
;AN000;
763 STI ;AN000; Turn interrupts on again.
764 CALL FAR PTR HOOK_INT_24
;AN000;
766 .IF < <WORD PTR EX_RE_DIR
> EQ EXEC_DIR
> ;AN000; Redirect Stdout?
767 MOV AH, 3EH
;AN000; Close Stdout.
770 MOV DX, OFFSET CON_DEVICE
;AN000; Open CON as stdout.
771 MOV AX, 3D01H
;AN000;
773 MOV AH, 3EH
;AN000; Close Stderr.
776 MOV DX, OFFSET CON_DEVICE
;AN000; Open CON as stdout.
777 MOV AX, 3D01H
;AN000;
782 POP DX ;AN000;JW get old DTA off
783 POP DS ;AN000;JW get old DTA seg
784 DOSCALL
;AN000;JW restore the DTA address
786 POP ES ;AN000; Restore all the registers.
788 POP BP ;AN000; Restore the base pointer
790 MOV AH, 4
DH ;AN000; Get the return code from the sub-process
792 .IF < AX NE
0 > or ;AN000; SAR;If not zero...
793 .IF < EXEC_ERR
eq TRUE
> ;AN000; SAR
795 MOV SUB_ERROR
,AL ;AN000;
796 STC ;AN000; Indicate there was an error
797 .ELSE ;AN000; Otherwise...
798 MOV SUB_ERROR
,0 ;AN000;
799 CLC ;AN000; No error.
801 MOV SUB_PROGRAM
, FALSE
;AN000;
802 MOV EXEC_FDISK
, FALSE
;AN000;DT reset FDISK flag
804 RET 8 ;AN000; Return, popping the parameters.
805 EXEC_PROGRAM_ROUTINE ENDP
;AN000;
806 ;************************************************************************
808 ; GET_CNTY_DEF_ROUTINE: Get country, keyboard and codepage for the
809 ; specified entry from the CTY_TABLE.
812 ; BX = 1: Use CTY_TAB_A
814 ; AX = index into country list table
817 ; N_COUNTRY = Country code
818 ; N_KYBD_VAL = 0: Keyboard code is not valid
819 ; = 1: Keyboard code is valid
820 ; S_KEYBOARD = Keyboard code (ASCII-N format)
821 ; N_CP_PRI = Primary code page
822 ; N_CP_SEC = Secondary code page
823 ; N_DESIGNATES = Number of disignates
824 ; N_CPSW = Cpsw status
825 ; N_CTY_RES = Reserved
828 ; OPERATION: The country code, keyboard, primary codepage and the
829 ; seondary codepage from the CTY_TABLE for the specified index is
830 ; returned as spedified above.
832 ; Note: Index of the first item is the table is 1.
834 ;****************************************************************************
835 PUBLIC GET_CNTY_DEF_ROUTINE
;AN000;
836 GET_CNTY_DEF_ROUTINE PROC
FAR ;AN000;
837 ; AX contains the search's start index
838 SUB AX, 1 ;AN000; Make the first index 0
839 MOV DX, TYPE CTY_DEF
;AN000; There are 9 bytes per entry
840 MUL DX ;AN000; Calculate the starting offset
841 MOV SI, AX ;AN000; Move the address into an index reg
843 .IF < BX EQ 1 > ;AN000; BX contains which table to search
844 ADD SI, OFFSET CTY_TAB_A_1
;AN000; Use the first table
846 ADD SI, OFFSET CTY_TAB_B_1
;AN000; Use the second table
849 COPY_WORD N_COUNTRY
, [SI+0] ;AN000; Get the counrty code
850 COPY_BYTE N_KYBD_VAL
, [SI+2] ;AN000; See if the keyboard is valid
851 MOV S_KEYBOARD
, 2 ;AN000; Length of the keyboard code string
852 COPY_WORD S_KEYBOARD
[2], [SI+3] ;AN000; Get the keyboard code string
853 COPY_WORD N_CP_PRI
, [SI+5] ;AN000; Get the primary code page
854 COPY_WORD N_CP_SEC
, [SI+7] ;AN000; Get the secondary code page
855 COPY_WORD N_DESIGNATES
, [SI+9] ;AN000; Get the number of designates
856 COPY_WORD N_CPSW
, [SI+11] ;AN000; Get the code page switching status
857 COPY_BYTE ALT_KYB_ID
, [SI+13] ;AN000; Get default alternate keyboard
858 COPY_BYTE N_CTY_RES
, [SI+14] ;AN000; A reserved byte
860 COPY_WORD I_KYBD_ALT
,2 ;AC090;JW
863 GET_CNTY_DEF_ROUTINE ENDP
;AN000;
864 ;****************************************************************************
866 ; GET_CNTY_INDEX_ROUTINE: Scan CTY_TABLE for the specified country code and
867 ; return index of country code into the table.
870 ; CX = The country code
873 ; DX = 1: Country code is in table CTY_TAB_A
874 ; = 2: Country code is in table CTY_TAB_B
875 ; BX = The index into the country list.
877 ; OPERATION: The CTY_TABLE is scanned for the specified country code and
878 ; the index into the table is returned.
880 ; Note: The index of the first item in the table is 1.
882 ;************************************************************************
883 PUBLIC GET_CNTY_INDEX_ROUTINE
;AN000;
884 GET_CNTY_INDEX_ROUTINE PROC
FAR ;AN000;
886 MOV DX, 1 ;AN000; Which table to search
887 MOV AH, 0 ;AN000; Clear the high byte
888 .WHILE < DX LE
2 > ;AN000; Search the TWO tables
889 .IF < DX EQ 1 > ;AN000; Are we searching the first table?
890 MOV SI, OFFSET CTY_TAB_A_1
;AN000; Yes! Get the offset of the table
891 MOV AL, CTY_TAB_A
;AN000; Get the number of entries
892 .ELSE ;AN000; Otherwise...
893 MOV SI, OFFSET CTY_TAB_B_1
;AN000; Get the offset of the second table
894 MOV AL, CTY_TAB_B
;AN000; Get the number of entries in this table
896 MOV BX, 1 ;AN000; Index currently being scaned
898 ; CX contains the country code.
899 .WHILE < <WORD PTR [SI]> NE
CX> AND ;AN000; Search until this code is found
900 .WHILE < BX LE
AX > ;AN000; And while there are still table entries
901 INC BX ;AN000; Increment the index into the table
902 ADD SI, TYPE CTY_DEF
;AN000; Point to the next table record
905 .IF < BX GT
AX > ;AN000; Index is finished for this table
906 INC DX ;AN000; Examine the next table
908 .LEAVE ;AN000; Exit the while loop
913 GET_CNTY_INDEX_ROUTINE ENDP
;AN000;
914 ;****************************************************************************
916 ; GET_KYBD_INDEX_ROUTINE: Scan KYBD_TABLE for the specified keyboard code and
917 ; return index of keyboard code in the table and the
918 ; alternate keyboard indicator.
921 ; DI = The offset of an ASCII-N string containing the keyboard code.
924 ; DX = 1: Keyboard is in table KYBD_TAB_A
925 ; = 2: Keyboard is in table KYBD_TAB_B
926 ; BX = The index into keyboard table.
927 ; AL = 0: No alternate keyboard
928 ; = 1: Alternate keyboard present
930 ; OPERATION: The KYBD_TABLE is scanned for the specifies keyboard code and
931 ; the index into the table is returned.
933 ; Note: The index of the first item in the table is 1.
935 ;************************************************************************
936 PUBLIC GET_KYBD_INDEX_ROUTINE
;AN000;
937 GET_KYBD_INDEX_ROUTINE PROC
FAR ;AN000;
939 MOV BX, 0 ;AN000; Zero the table index
940 MOV DX, 1 ;AN000; Which table to search
941 MOV AH, 0 ;AN000; Clear high byte to use 16-bit value
942 .WHILE < DX LE
2 > ;AN000;
943 .IF < DX EQ 1 > ;AN000;
944 MOV SI, OFFSET KYBD_TAB_A_1
;AN000; Get the offset of the table
945 MOV AL, KYBD_TAB_A
;AN000; Get the number of entries
947 MOV SI, OFFSET KYBD_TAB_B_1
;AN000; Get the offset of the second table
948 MOV AL, KYBD_TAB_B
;AN000; Get the number of entries in this table
950 MOV BX, 1 ;AN000; Index currently being scaned
952 MOV CX, WORD PTR [DI+2] ;AN000; Get the keyboard code
953 .WHILE < <WORD PTR [SI]> NE
CX> AND ;AN000;
954 .WHILE < BX LE
AX > ;AN000;
956 ADD SI, TYPE KYB_DEF
;AN000;
959 .IF < BX GT
AX > ;AN000; Index is finished for this table
960 INC DX ;AN000; Examine the next table
962 MOV AL, BYTE PTR [SI+2] ;AN000; Get the alternate keyboard flag
963 .LEAVE ;AN000; Exit the while loop
969 GET_KYBD_INDEX_ROUTINE ENDP
;AN000;
970 ;************************************************************************;
972 ; GET_KYBD_ROUTINE: Get the keyboard code and the alternate keyboard
973 ; indicator from the KYBD_TABLE for the item specified by the index
974 ; into the keyboard table.
977 ; CX = 1: Keyboard code is in table KYBD_TAB_A
978 ; = 2: Keyboard code is is table KYBD_TAB_B
979 ; AX = index into the keyboard table.
980 ; DI = Address of the keyboard code. (ASCII-N format)
983 ; AL = 0: No alternate keyboard
984 ; = 1: Alternate keyboard present
986 ; OPERATION: The keyboard code from the KYBD_TABLE for the specified
987 ; index item is returned. Also, the alternate keyboard present
988 ; variable is updated.
990 ; Note: Index of the first item in the table is 1.
992 ;****************************************************************************
993 PUBLIC GET_KYBD_ROUTINE
;AN000;
994 GET_KYBD_ROUTINE PROC
FAR ;AN000;
995 ; AX contins the search's start index
996 SUB AX, 1 ;AN000; Make the first index 0
997 MOV DX, TYPE KYB_DEF
;AN000; There are 3 bytes per entry
998 MUL DX ;AN000; Calculate the offset into the table
999 MOV SI, AX ;AN000; Move the address into an index reg
1000 .IF < CX EQ 1> ;AN000; CX Contains which table to search
1001 ADD SI, OFFSET KYBD_TAB_A_1
;AN000;
1003 ADD SI, OFFSET KYBD_TAB_B_1
;AN000;
1006 MOV WORD PTR [DI], 2 ;AN000; Length of the string
1007 COPY_WORD
[DI+2], [SI] ;AN000; Get the keyboard name
1008 MOV AL, [SI+2] ;AN000; See if there is an alternate keyboard
1011 GET_KYBD_ROUTINE ENDP
;AN000;
1012 ;;************************************************************************
1014 ;; CHK_EX_MEM_ROUTINE: Check if the system supports expanded memory.
1020 ;; SI = 0: Expanded memory is NOT supported.
1021 ;; = 1: Expanded memory is supported.
1025 ;; OPERATION: A call to the system services (INT 15H, AH = C0H) is performed
1026 ;; to get the system configuration parameters. (model byte).
1028 ;; The Personal System/2 Model 80 (model byte = 0F8h) always support
1031 ;; The Personal System/2 Models 50 and 60 (model byte = 0FCh) support
1032 ;; expanded memory if the CATSKILL 2 is present. The CATSKILL 2 card has
1033 ;; the identity number of F7FEh. F7H is read through the port address
1034 ;; 101h and FEH is read through port 100H
1036 ;; The PS2 50/60 also support expanded memory if the HOLSTER card is
1037 ;; is present (id = FEFEh).
1039 ;; AT's (and some XT's ?) support expanded memory if the CATSKILL 1
1040 ;; (XMA) card is present.
1042 ;; All other models do not support expanded memory.
1044 ;;************************************************************************
1045 SLOT_SETUP EQU
08h ;AN000;Mask to put the desired adapter @RH2
1046 CARD_ID_LO EQU 100H
;AN000;PS/2 Adapter card id low and @RH2
1047 CARD_ID_HI EQU 101H
;AN000; high bytes - read only @RH2
1048 ;Card IDs read from port 100,101 @RH2
1049 XMAA_CARD_ID EQU
0FEF7h ;AN000; XMA/A Card ID @RH2
1050 HLST_CARD_ID EQU
0FEFEh ;AN000; HOLSTER card id JW
1051 MODE_REG EQU 31A7H
;AN000; Mode register
1052 TTPOINTER EQU 31A0H
;AN000; Translate Table Pointer (word)
1054 NUM_OF_SLOTS EQU
8 ;AN000;
1056 PUBLIC CHK_EX_MEM_ROUTINE
;AN000;
1057 CHK_EX_MEM_ROUTINE PROC
FAR ;AN000;
1060 MOV AH, 0C0H ;AN000; Function number to get the model byte
1062 .IF < AH eq 80H
> ;AN000;IF AH = 80H
1063 MOV SI, 0 ;AN000;then this is a PC or PCjr. No Expanded memory
1064 MOV BX, 0 ;AN000;JW not a model 80
1066 .IF < AH ne
086H > ;AN000;If not an old XT or AT
1067 MOV AH, BYTE PTR ES:[BX]+2 ;AN000; Get the model byte
1068 MOV AL, BYTE PTR ES:[BX]+3 ;AN000; Get the sub-model byte
1070 .IF < AH eq 0F8H> ;AN000; Is this a model 80?
1071 MOV SI, 1 ;AN000; Yes! Expanded memory supported
1073 .ELSEIF
< AH eq 0FCH > and ;AN000; Is this a model 50 or 60?
1074 .IF < AL eq 04 > or ;AN000;
1075 .IF < AL eq 05 > ;AN000;
1076 ;-------------------------------------
1077 ; Search for XMA/A cards �
1078 ;-------------------------------------
1079 XOR CX,CX ;AN000;Check all slots starting at 0 @RH2
1080 MOV BX,0 ;AN000;JW say not a model 80
1083 MOV AL,CL ;AN000;Enable the specific slot by ORing @RH2
1084 OR AL,SLOT_SETUP
;AN000; the slot (bits 0-2) with the @RH2
1085 OUT 96H
,AL ;AN000; setup flag (bit 3). @RH2
1087 MOV DX,CARD_ID_LO
;AN000;Read the signature ID of the card @RH2
1088 IN AL,DX ;AN000; @RH2
1089 XCHG AL,AH ;AN000; @RH2
1090 MOV DX,CARD_ID_HI
;AN000; @RH2
1091 IN AL,DX ;AN000; @RH2
1093 .IF < AX eq XMAA_CARD_ID
> or ;AN000;
1094 .IF < AX eq HLST_CARD_ID
> ;AN000;JW
1095 MOV SI, 1 ;AN000; Yes! Expanded memory supported
1099 .IF < CL eq NUM_OF_SLOTS
> ;AN000;
1100 MOV SI, 0 ;AN000; No! Expanded memoory isn't supported
1104 INC CL ;AN000;Check next adapter slot @RH2
1108 OUT 96H
,AL ;AN000;JW Reset port to neutral state
1110 .ELSE ;AN000; AT or XT
1111 ;-------------------------------------
1112 ; Search for XMA cards �
1113 ;-------------------------------------
1114 MOV DX,MODE_REG
;AN000;SAVE CONTENTS OF MODE REG
1118 MOV AX,0AA55H ;AN000;DATA PATTERN (IN REAL MODE)
1119 ;BE CERTAIN MODE REG GETS
1121 MOV DX,MODE_REG
;AN000;I/O TO MODE REG
1122 OUT DX,AL ;AN000;WRITE PATTERN
1123 MOV DX,TTPOINTER
+ 1 ;AN000;I/O TO TT POINTER (ODD ADDR)
1124 XCHG AL,AH ;AN000;CHRG BUS WITH INVERSE PATTERN
1125 OUT DX,AL ;AN000;WRITE IT
1126 MOV DX,MODE_REG
;AN000;
1127 IN AL,DX ;AN000;READ BACK MODE REG
1129 AND AL,0FH ;AN000;MASK OFF UNUSED BITS
1130 ;ZERO FLAG = 0 IF ERROR
1132 PUSHF ;AN000;SAVE FLAGS
1133 MOV DX,MODE_REG
;AN000;
1134 OUT DX,AL ;AN000;RESTORE MODE REG TO INITIAL STATE
1135 POPF ;AN000;RESTORE FLAGS
1137 MOV SI,1 ;AN000;XMA card present
1139 MOV SI,0 ;AN000;no XMA card present
1141 MOV BX,0 ;AN000;not a model 80
1146 CHK_EX_MEM_ROUTINE ENDP
;AN000;
1147 ;****************************************************************************
1149 ; GET_PRINTER_PARAMS_ROUTINE: Get parameters for specified printer.
1152 ; AX = The printer number.
1153 ; BX = The number of the port to retrieve the information on.
1154 ; If var_port = 0, the information that is returned is
1155 ; that which corresponds to var_prt.
1156 ; BX = 0 : Get the information on printer number VAR_PRT
1157 ; = 1 : Get the information for the printer attached to LPT1
1158 ; = 2 : Get the information for the printer attached to LPT2
1159 ; = 3 : Get the information for the printer attached to LPT3
1160 ; = 4 : Get the information for the printer attached to COM1
1161 ; = 5 : Get the information for the printer attached to COM2
1162 ; = 6 : Get the information for the printer attached to COM3
1163 ; = 7 : Get the information for the printer attached to COM4
1166 ; AX = 1: Printer information is valid
1167 ; = 0: Printer not valid: default values returned
1169 ; OPERATION: Printer information for the specified printer is returned.
1170 ; If the specified printer is not defined, default values will be
1172 ; I_PRINTER = Index into printer list (16 bit variable) : default 1
1173 ; N_PRINTER_TYPE = P: Parallel printer
1174 ; = S: Serial printer
1175 ; I_PORT = Port number (16 bit variable) : default 1
1176 ; I_REDIRECT = Redirection port number (16 bit variable) : default 1
1177 ; S_MODE_PARM = Mode parameters - ASCII-N format
1178 ; S_CP_DRIVER = Code page driver parameters - ASCII-N format
1179 ; S_CP_PREPARE = Code prepare parameters - ASCII-N format
1180 ; S_GRAPH_PARM = Graphics parameters - ASCII-N format
1182 ; The structures of printer information are searched for the one with
1183 ; the same number as specified by AX. If found, the information
1184 ; in that structure is returned in the variables listed above.
1186 ;****************************************************************************
1187 PUBLIC GET_PRINTER_PARAMS_ROUTINE
;AN000;
1188 GET_PRINTER_PARAMS_ROUTINE PROC
FAR ;AN000;
1190 .IF < BX NE
0 > ;AN000;
1192 MOV AX, TYPE PRINTER_DEF
;AN000;
1195 .IF < PRINTER_TABLES
[SI].PRINTER_DATA_VALID
EQ 1 > ;AN000;
1196 JMP COPY_INFO
;AN000;
1198 JMP RETURN_DEFAULTS
;AN000;
1201 MOV SI, 0 ;AN000; Index into the printer table
1202 MOV BX, 1 ;AN000; Which structure is being searched
1203 .WHILE < BX BE
7 > ;AN000; Search the seven structures
1204 .IF < PRINTER_TABLES
[SI].PRINTER_TAB_NUM
EQ AX > AND ;AN000; Does the printer number match?
1205 .IF < PRINTER_TABLES
[SI].PRINTER_DATA_VALID
EQ 1 > ;AN000; And is this data valid?
1206 JMP COPY_INFO
;AN000;
1208 ADD SI, TYPE PRINTER_DEF
;AN000; Search the next structure
1211 RETURN_DEFAULTS: ;AN000;
1212 MOV I_PRINTER
, 1 ;AN000; Yes! Return the default information
1213 MOV I_PORT
, 1 ;AN000;
1214 MOV I_REDIRECT
, 1 ;AN000;
1215 MOV S_MODE_PARM
, 0 ;AN000;
1216 MOV S_CP_DRIVER
, 0 ;AN000;
1217 MOV S_CP_PREPARE
, 0 ;AN000;
1218 MOV S_GRAPH_PARM
, 0 ;AN000;
1219 MOV AX, 0 ;AN000; Indicate that the default values are being returned
1220 JMP EXIT_GET_PARAMS
;AN000;
1224 COPY_WORD I_PRINTER
, PRINTER_TABLES
[SI].PRINTER_INDEX
;AN000; Copy the data out of the structure
1225 COPY_BYTE N_PRINTER_TYPE
, PRINTER_TABLES
[SI].PRINTER_TYPE
;AN000;
1226 COPY_WORD I_PORT
, PRINTER_TABLES
[SI].PORT_NUMBER
;AN000;
1227 COPY_WORD I_REDIRECT
, PRINTER_TABLES
[SI].REDIRECTION_PORT
;AN000;
1229 COPY_STRING S_MODE_PARM
, 40, PRINTER_TABLES
[SI].MODE_PARMS
;AN000;
1232 COPY_STRING S_CP_DRIVER
, 22, PRINTER_TABLES
[SI].CODE_DRIVER
;AN000;
1235 COPY_STRING S_CP_PREPARE
, 12, PRINTER_TABLES
[SI].CODE_PREPARE
;AN000;
1238 COPY_STRING S_GRAPH_PARM
, 20, PRINTER_TABLES
[SI].GRAPHICS_PARMS
;AN000;
1240 MOV AX, 1 ;AN000; Return that the data is valid
1242 EXIT_GET_PARAMS: ;AN000;
1245 GET_PRINTER_PARAMS_ROUTINE ENDP
;AN000;
1246 ;****************************************************************************
1248 ; SAVE_PRINTER_PARAMS_ROUTINE: Save the printer information in the printer
1252 ; AX = The printer number.
1257 ; OPERATION: Printer information for the specified printer is stored.
1258 ; I_PRINTER = Index into printer list (16 bit variable) : default 1
1259 ; N_PRINTER_TYPE = P: Parallel printer
1260 ; = S: Serial printer
1261 ; I_PORT = Port number (16 bit variable) : default 1
1262 ; I_REDIRECT = Redirection port number (16 bit variable) : default 1
1263 ; S_MODE_PARM = Mode parameters - ASCII-N format
1264 ; S_CP_DRIVER = Code page driver parameters - ASCII-N format
1265 ; S_CP_PREPARE = Code prepare parameters - ASCII-N format
1266 ; S_GRAPH_PARM = Graphics parameters - ASCII-N format
1268 ; The information is stored in the structures according to the type
1269 ; and port number of this printer. The first three structures are for
1270 ; LPT1 - LPT3, while the next four are for COM1 - COM2.
1272 ;****************************************************************************
1273 PUBLIC SAVE_PRINTER_PARAMS_ROUTINE
;AN000;
1274 SAVE_PRINTER_PARAMS_ROUTINE PROC
FAR ;AN000;
1276 PUSH AX ;AN000; Save the printer number
1277 MOV AX, TYPE PRINTER_DEF
;AN000; Get the size of each structure
1278 MOV SI, I_PORT
;AN000; Get the port number
1279 .IF < N_PRINTER_TYPE
EQ 'S'> ;AN000; Is this a serial port?
1280 ADD SI, 3 ;AN000; Yes! Store in the later 4 structures
1282 DEC SI ;AN000; Make the first index a 0
1283 MUL SI ;AN000; Calculate the address of the structure
1284 MOV BX, AX ;AN000; Put address into an index register
1285 COPY_WORD PRINTER_TABLES
[BX].PRINTER_INDEX
, I_PRINTER
;AN000; Copy the data into the structure
1286 COPY_BYTE PRINTER_TABLES
[BX].PRINTER_TYPE
, N_PRINTER_TYPE
;AN000;
1287 COPY_WORD PRINTER_TABLES
[BX].PORT_NUMBER
, I_PORT
;AN000;
1288 COPY_WORD PRINTER_TABLES
[BX].REDIRECTION_PORT
, I_REDIRECT
;AN000;
1289 COPY_STRING PRINTER_TABLES
[BX].MODE_PARMS
, 40, S_MODE_PARM
;AC000;JW
1290 COPY_STRING PRINTER_TABLES
[BX].CODE_DRIVER
, 22, S_CP_DRIVER
;AN000;
1291 COPY_STRING PRINTER_TABLES
[BX].CODE_PREPARE
, 12, S_CP_PREPARE
;AN000;
1292 COPY_STRING PRINTER_TABLES
[BX].GRAPHICS_PARMS
, 20, S_GRAPH_PARM
;AN000;
1293 .IF <I_PORT
EQ 1 > ;AN029;
1294 COPY_STRING S_GRAPHICS
,M_GRAPHICS
,S_GRAPH_PARM
;AN029;
1296 POP AX ;AN000; Restore the printer number
1297 MOV PRINTER_TABLES
[BX].PRINTER_TAB_NUM
, AX ;AN000; Save the number
1298 MOV PRINTER_TABLES
[BX].PRINTER_DATA_VALID
, 1 ;AN000; Indicate that the data is valid
1302 .WHILE < CX BE
7 > ;AN000;
1303 .IF < PRINTER_TABLES
[SI].PRINTER_TAB_NUM
EQ AX > AND ;AN000;
1304 .IF < SI NE
BX > ;AN000;
1305 MOV PRINTER_TABLES
[SI].PRINTER_DATA_VALID
, 0 ;AN000;
1307 ADD SI, TYPE PRINTER_DEF
;AN000;
1313 SAVE_PRINTER_PARAMS_ROUTINE ENDP
;AN000;
1314 ;****************************************************************************
1316 ; DISPLAY_MESSAGE_ROUTINE: Call the message retriever to display a message.
1319 ; AX = The number of the message to be displayed. (16 bit value)
1322 ; If CY = 1, there was an error displaying the message.
1323 ; If CY = 0, there were no errors.
1327 ;****************************************************************************
1328 PUBLIC DISPLAY_MESSAGE_ROUTINE
;AN000;
1329 DISPLAY_MESSAGE_ROUTINE PROC
FAR ;AN000; AX already contains the message number
1330 MOV BX, -1 ;AN000; HANDLE -1 ==> USE ONLY DOS FUNCTION 1-12
1331 MOV SI, 0 ;AN000; SUBSTITUTION LIST
1332 MOV CX, 0 ;AN000; SUBSTITUTION COUNT
1333 MOV DL, 00 ;AN000; DOS INT21H FUNCTION FOR INPUT 0==> NO INPUT
1334 MOV DI, 0 ;AN000; INPUT BUFFER IF DL = 0AH
1335 MOV DH, -1 ;AN000; MESSAGE CALL -1==> UTILITY MESSAGE
1336 CALL SYSDISPMSG
;AN000;
1338 DISPLAY_MESSAGE_ROUTINE ENDP
;AN000;
1340 ;****************************************************************************
1341 ; Procedure for hooking the INT_23_VECTOR into vector table
1346 ;****************************************************************************
1347 PUBLIC HOOK_INT_23
;AN074;SEH
1348 HOOK_INT_23 PROC
FAR ;AN074;SEH
1353 PUSH ES ;AN074;SEH Save the segment registers.
1357 MOV AL, 23H
;AN074;SEH Interrupt number to get the vector of
1358 MOV AH, 35H
;AN074;SEH DOS Function number for getting a vector
1359 DOSCALL
;AN074;SEH Get the interrupt vector
1360 MOV WORD PTR OLD_INT_23
, BX ;AN074;SEH Save the old vactor offset
1361 MOV AX, ES ;AN074;SEH Get the old vector segment
1362 MOV WORD PTR OLD_INT_23
[2], AX ;AN074;SEH Save the old vector segment
1363 PUSH DS ;AN074;SEH Save DS
1364 PUSH CS ;AN074;SEH Point DS to the current code segment
1366 MOV DX, OFFSET INT_23_VECTOR
;AN074;SEH Load offset of the new vector
1367 MOV AL, 23H
;AN074;SEH Interrupt number to set
1368 MOV AH, 25H
;AN074;SEH DOS Fn. number for setting a vector
1369 DOSCALL
;AN074;SEH Set the vector
1370 POP DS ;AN074;SEH Restore data segment
1373 POP DS ;AN074;SEH Restore the registers
1380 HOOK_INT_23 ENDP
;AN074;SEH
1382 ;****************************************************************************
1383 ; Procedure for restoring the old interrupt 23h vector.
1388 ;****************************************************************************
1389 PUBLIC RESTORE_INT_23
;AN074;SEH
1390 RESTORE_INT_23 PROC
FAR ;AN074;SEH
1395 PUSH DS ;AN074;SEH Save the data segment
1397 PUSH DS ;AN074;SEH Save DS
1398 LDS DX, OLD_INT_23
;AN074;SEH Load the address of the old vector
1399 MOV AH, 25H
;AN074;SEH DOS Fn. number for setting an interrupt vector
1400 MOV AL, 23H
;AN074;SEH Interrupt vector to set
1401 DOSCALL
;AN074;SEH Set the vector
1402 POP DS ;AN074;SEH Restore data segment
1404 POP DS ;AN074;SEH Restore the data segment
1410 RESTORE_INT_23 ENDP
;AN074;SEH
1411 ;****************************************************************************
1412 ; Procedure for hooking the INT_24_VECTOR into vector table
1417 ;****************************************************************************
1418 PUBLIC HOOK_INT_24
;AN000;
1419 HOOK_INT_24 PROC
FAR ;AN000;
1424 PUSH ES ;AN000; Save the segment registers.
1428 .IF < INT24_STATUS
eq UNHOOKED
> ;AN000;
1430 MOV AL, 24H
;AN000; Interrupt number to get the vector of
1431 MOV AH, 35H
;AN000; DOS Function number for getting a vector
1432 DOSCALL
;AN000; Get the interrupt vector
1433 MOV WORD PTR OLD_INT_24
, BX ;AN000; Save the old vactor offset
1434 MOV AX, ES ;AN000; Get the old vector segment
1435 MOV WORD PTR OLD_INT_24
[2], AX ;AN000; Save the old vector segment
1436 PUSH DS ;AN000; Save DS
1437 PUSH CS ;AN000; Point DS to the current code segment
1439 MOV DX, OFFSET INT_24_VECTOR
;AN000; Load offset of the new vector
1440 MOV AL, 24H
;AN000; Interrupt number to set
1441 MOV AH, 25H
;AN000; DOS Fn. number for setting a vector
1442 DOSCALL
;AN000; Set the vector
1443 POP DS ;AN000; Restore data segment
1444 MOV INT24_STATUS
,HOOKED
;AN000;
1449 POP DS ;AN000; Restore the registers
1456 HOOK_INT_24 ENDP
;AN000;
1458 ;****************************************************************************
1459 ; Procedure for restoring the old interrupt 24h vector.
1464 ;****************************************************************************
1465 PUBLIC RESTORE_INT_24
;AN000;
1466 RESTORE_INT_24 PROC
FAR ;AN000;
1471 PUSH DS ;AN000; Save the data segment
1473 .IF < INT24_STATUS
eq HOOKED
> ;AN000;
1475 PUSH DS ;AN000; Save DS
1476 LDS DX, OLD_INT_24
;AN000; Load the address of the old vector
1477 MOV AH, 25H
;AN000; DOS Fn. number for setting an interrupt vector
1478 MOV AL, 24H
;AN000; Interrupt vector to set
1479 DOSCALL
;AN000; Set the vector
1480 POP DS ;AN000; Restore data segment
1481 MOV INT24_STATUS
,UNHOOKED
;AN000;
1485 POP DS ;AN000; Restore the data segment
1491 RESTORE_INT_24 ENDP
;AN000;
1492 ;****************************************************************************
1493 ; Procedure for hooking the INT_2F_VECTOR into vector table
1498 ;****************************************************************************
1499 PUBLIC HOOK_INT_2F
;AN000;
1500 PUBLIC RESTORE_INT_2F
;AN000;
1501 HOOK_INT_2F PROC
FAR ;AN000;
1506 PUSH ES ;AN000; Save the segment registers.
1508 MOV AL, 2FH
;AN000; Interrupt number to get the vector of
1509 MOV AH, 35H
;AN000; DOS Function number for getting a vector
1510 DOSCALL
;AN000; Get the interrupt vector
1511 MOV WORD PTR OLD_INT_2F
, BX ;AN000; Save the old vactor offset
1512 MOV AX, ES ;AN000; Get the old vector segment
1513 MOV WORD PTR OLD_INT_2F
[2], AX ;AN000; Save the old vector segment
1514 PUSH CS ;AN000; Point DS to the current code segment
1516 MOV DX, OFFSET INT_2F_VECTOR
;AN000; Load offset of the new vector
1517 MOV AL, 2FH
;AN000; Interrupt number to set
1518 MOV AH, 25H
;AN000; DOS Fn. number for setting a vector
1519 DOSCALL
;AN000; Set the vector
1520 POP DS ;AN000; Restore the registers
1528 HOOK_INT_2F ENDP
;AN000;
1529 ;****************************************************************************
1530 ; Procedure for restoring the old interrupt 2Fh vector.
1535 ;****************************************************************************
1536 RESTORE_INT_2F PROC
FAR ;AN000;
1540 PUSH DS ;AN000; Save the data segment
1541 LDS DX, OLD_INT_2F
;AN000; Load the address of the old vector
1542 MOV AH, 25H
;AN000; DOS Fn. number for setting an interrupt vector
1543 MOV AL, 2FH
;AN000; Interrupt vector to set
1544 DOSCALL
;AN000; Set the vector
1545 POP DS ;AN000; Restore the data segment
1550 RESTORE_INT_2F ENDP
;AN000;
1551 ;****************************************************************************
1552 ; Procedure for hooking the INT_2F_256KB into vector table
1557 ;****************************************************************************
1558 PUBLIC HOOK_INT_2F_256KB
;AN000;
1559 HOOK_INT_2F_256KB PROC
FAR ;AN000;
1564 PUSH ES ;AN000; Save the segment registers.
1566 MOV AL, 2FH
;AN000; Interrupt number to get the vector of
1567 MOV AH, 35H
;AN000; DOS Function number for getting a vector
1568 DOSCALL
;AN000; Get the interrupt vector
1569 MOV WORD PTR OLD_INT_2F
, BX ;AN000; Save the old vactor offset
1570 MOV AX, ES ;AN000; Get the old vector segment
1571 MOV WORD PTR OLD_INT_2F
[2], AX ;AN000; Save the old vector segment
1572 PUSH CS ;AN000; Point DS to the current code segment
1574 MOV DX, OFFSET INT_2F_256KB
;AN000; Load offset of the new vector
1575 MOV AL, 2FH
;AN000; Interrupt number to set
1576 MOV AH, 25H
;AN000; DOS Fn. number for setting a vector
1577 DOSCALL
;AN000; Set the vector
1578 POP DS ;AN000; Restore the registers
1586 HOOK_INT_2F_256KB ENDP
;AN000;
1587 ;****************************************************************************
1588 ; Procedure for hooking the INT_2F_FORMAT into vector table
1593 ;****************************************************************************
1594 PUBLIC HOOK_INT_2F_FORMAT
;AN111;JW
1595 HOOK_INT_2F_FORMAT PROC
FAR ;AN111;JW
1600 PUSH ES ;AN111; Save the segment registers. JW
1602 MOV AL, 2FH
;AN111; Interrupt number to get the vector of JW
1603 MOV AH, 35H
;AN111; DOS Function number for getting a vector JW
1604 DOSCALL
;AN111; Get the interrupt vector JW
1605 MOV WORD PTR OLD_INT_2F
, BX ;AN111; Save the old vactor offset JW
1606 MOV AX, ES ;AN111; Get the old vector segment JW
1607 MOV WORD PTR OLD_INT_2F
[2], AX ;AN111; Save the old vector segment JW
1608 PUSH CS ;AN111; Point DS to the current code segment JW
1610 MOV DX, OFFSET INT_2F_FORMAT
;AN111; Load offset of the new vector JW
1611 MOV AL, 2FH
;AN111; Interrupt number to set JW
1612 MOV AH, 25H
;AN111; DOS Fn. number for setting a vector JW
1613 DOSCALL
;AN111; Set the vector JW
1614 POP DS ;AN111; Restore the registers JW
1622 HOOK_INT_2F_FORMAT ENDP
;AN111;JW
1623 ;****************************************************************************
1625 CODE_FAR ENDS
;AN000;