;/*
; *                      Microsoft Confidential
; *                      Copyright (C) Microsoft Corporation 1991
; *                      All Rights Reserved.
; */

;                       $SALUT (4,25,30,41)
;******************* START OF SPECIFICATIONS ***********************************
;
; MODULE NAME:          PRINT.COM
;
; DESCRIPTIVE NAME:     DOS PRINT program for background printing of
;                       text files to the list device.
;
; FUNCTION:             DOS PRINT program for background printing of
;                       text files to the list device.  The utility is
;                       constructed of 3 .SAL files. They are:
;
;                               PRINT_R.SAL  - The resident portion of PRINT
;                               PRINT_T.SAL  - The transient portion of PRINT
;                               PRINT_SR.SAL - The service routines of PRINT
;
;                       NOTE:   The Link order is VERY important for this module.
;                               This is due to the Resident/Transient nature of
;                               PRINT.
;
;                               INT 28H is a software interrupt generated by the
;                               DOS in  its  I/O  wait  loops.   This spooler
;                               can be assembled for operation using only this
;                               interrupt  which  is  portable  from system to
;                               system.  It may also be assembled to use a
;                               hardware timer interrupt in addition to the
;                               software  INT  28H.   The purpose  of  using
;                               hardware interrupts is to allow printing to
;                               continue during programs which do not  enter
;                               the system and therefore causes the INT 28H to
;                               go away.  A timer interrupt is chosen in
;                               preference to a "printer buffer empty" interrupt
;                               because PRINT in the timer form is generic.  It
;                               can be given the name of any currently installed
;                               character device as the "printer", this makes it
;                               portable to devices which are installed by the
;                               user even in the hardware case.  It could be
;                               Revised to use a buffer empty interrupt (no
;                               code is given for this case), if this is done
;                               the PROMPT and BADMES messages and their
;                               associated  code should be removed as PRINT will
;                               then be device specific.
;
;       NOTE From Aaron Reynolds
;
; BEWARE ALL YEE WHO ENTER HERE.
;    PRINT is an amazingly complex program.  MS-DOS versions below 3.00 are
;    NOT re-entrant, this means that this utility is basically not a
;    possibility.  It gets by on the fact that it is written by the same
;    person who wrote the OS.  Since you are not that person, you must be very
;    careful about making any modification to this utility.  There are a
;    number of things which may seem to be unnecessary on first examination.
;    BEWARE, almost every line of code is there for a very good reason.  The
;    order of things is very carefully chosen.  PRINT is full of potential
;    windows, make sure that you do not open one by careless modification.  Do
;    not look for a lot of help from the comments, a complete explanation
;    would probably fill a book.  A succesful modifier will have an in-depth
;    knowledge of the internal function of MS-DOS, and of the PRINT utility
;    itself through in depth study of the comments AND the code.
;
; ENTRY POINT:
;
; INPUT:
;
; EXIT NORMAL:
;
; EXIT ERROR:
;
; INTERNAL REFERENCES:
;
;       ROUTINES:
;
;       DATA AREAS:
;
; EXTERNAL REFERENCES:
;
;       ROUTINES:
;
;       DATA AREAS:
;
; NOTES:
;
; REVISION HISTORY: Ax000  Version 4.0  05/01/87 - first release              FG
;                   Ax001  DCR D201              - Extended Atrib change      FG
;                   Ax002  P 1175                - move msgs back to TRANS    FG
;                   Ax003  P 1487                - PARSE error message problemFG
;                   Ax004  P 1546                - PARSE error trailing :     FG
;                   Ax005  P 1717                - multiples of same switch   FG
;                   Ax006  P 1996                - Extended open error        FG
;                   Ax007  P 2052                - [PRN] prompt lpt1 error    FG
;                   Ax008  P 2053                - CPSW prints empty file     FG
;                   Ax009  P 2229                - filename truncation        FG
;                   Ax010  D  389                - use transname /server DOS  FG
;                   Ax011  P 3122                - attrib missing /server DOS FG
;                   Ax012  P 3949                - Error in opening an open   FG
;                   Ax013  P 3949                - open mode - second attempt FG
;                   Ax014  P 4396                - some messages need STDOUT  FG
;                   Ax015  P 4880                - DRIVERS not recognized     FG
;
; PRE-VERSION 4.0 HISTORY:
;
;       V1.00   07/03/82
;       V2.00   07/05/83        A.R
;               New INT 2FH interface, Pathnames, context switch.
;       V2.50   09/14/83        M.A.U
;               Turned it back to a print
;               11/21/83        M.A.U
;               Repaired bug in file cancel code
;               11/28/83        M.A.U
;               Added int 23 and 24 handlers to transient.
;               01/27/84        M.A.U
;               Allways checks for valid drive.
;       V3.00   02/03/84        M.A.U
;               Partitioned so as to assemble on a PC
;               By the by, it is V3.00 now.
;               05/23/85        K.G.S
;               Chains into INT19 (bootstrap) to unhook
;               INT_1C (timer) and INT_15 (AT's Wait On Event)
;
; COPYRIGHT: "The DOS PRINT Utility"
;            "Version 4.00 (C) Copyright 1988 Microsoft
;            "Licenced Material - Program Property of Microsoft"
;
;
;******************* END OF SPECIFICATIONS *************************************
                        subttl PRINT - Program Organization
                        page
;******************* START PROGRAM ORGANIZATION *******************************
;
;
;Group / Label        Contents              File
;              ZDDDDDDDDDDDDDDDDD? D?
;CODER         3  Data buffer    3  C PRINT_RM
;              CMMMMMMMMMMMMMMMMM4 DY
;              3                 3 D?
;              3  Resident       3  3
;              3    Code         3  3
;              3                 3  3
;filequeue --- CDDDDDDDDDDDDDDDDD4  3
;              3  Resident       3  3
;              3    Initalization3  CD  PRINT_R
;              3      Code       3  3
;              CDDDDDDDDDDDDDDDDD4  3
;              CMMMMMMMMMMMMMMMMM4 DY
;              3  CL1 data       3  3
;              CDDDDDDDDDDDDDDDDD4  3
;              3  CL2 data       3
;              CDDDDDDDDDDDDDDDDD4  3
;              3  CLB data       3  3
;              CDDDDDDDDDDDDDDDDD4  CD  PRINT_TM
;              3  CLC data       3  3
;              CDDDDDDDDDDDDDDDDD4  3
;              3  CLD data       3  3
;              CMMMMMMMMMMMMMMMMM4 DY
;DG            3  Transient      3 D?
;              3    code         3  3
;              CDDDDDDDDDDDDDDDDD4  3
;              3  DispMsg        3  3
;              CDDDDDDDDDDDDDDDDD4  3
;              3  SYSMSG         3  3
;              3    Code         3  3
;              3  Parser         3  3
;              CDDDDDDDDDDDDDDDDD4  3
;              3  Transient      3  CD  PRINT_T
;              3    data         3  3
;              CDDDDDDDDDDDDDDDDD4  3
;              3  Stack          3  3
;transsize --- @DDDDDDDDDDDDDDDDDY DY
;
;
;*******************  END  ROGRAM ORGANIZATION  ********************************

                        subttl PRINT - Data Space
                        page
INCLUDE VERSION.INC
INCLUDE SYSVAR.INC

FALSE                   EQU  0
TRUE                    EQU  NOT FALSE

                        IF   MSVER
HARDINT                     EQU  FALSE  ;No hardware ints
AINT                        EQU  FALSE  ;No need to do interrupt acknowledge
                        ENDIF

                        IF   IBM
HARDINT                     EQU  TRUE
INTLOC                      EQU  1CH    ;Hardware interrupt location (Timer)
REBOOT                      EQU  19H    ;ROM BIOS "Bootstrap"
AINT                        EQU  TRUE   ;Acknowledge interrupts
EOI                         EQU  20H    ;End Of Interrupt "instruction"
AKPORT                      EQU  20H    ;Interrupt Acknowledge port
                        ENDIF

;  The following values have to do with the ERRCNT variable and the CNTMES
;  message.  The values define levels at wich it is assumed an off-line error
;  exists.  ERRCNT1 defines the value of ERRCNT above which the CNTMES message
;  is printed by the transient.  ERRCNT2 defines the value of ERRCNT above
;  which the resident will give up trying to print messages on the printer, it
;  is much greater than ERRCNT1 because a much tighter loop is involved.  The
;  bounding event which determines the correct value is the time required to
;  do a form feed.

                        IF   IBM
ERRCNT1                     EQU  1500
ERRCNT2                     EQU  20000
                        ELSE
ERRCNT1                     EQU  1500
ERRCNT2                     EQU  20000
                        ENDIF


;WARNING DANGER WARNING:
;   PRINT is a systems utility. It is clearly understood that it may have
;   to be entirely re-written for future versions of MS-DOS. The following
;   TWO vectors are version specific, they may not exist at all in future
;   versions. If they do exist, they may function differently.
; ANY PROGRAM WHICH IMITATES PRINTS USE OF THESE VECTORS IS ALSO A SYSTEMS
; UTILITY AND IS THEREFORE NOT VERSION PORTABLE IN ANY WAY SHAPE OR FORM.
; YOU HAVE BEEN WARNED, "I DID IT THE SAME WAY PRINT DID" IS NOT AN REASON
; TO EXPECT A PROGRAM TO WORK ON FUTURE VERSIONS OF MS-DOS.

SOFTINT                 EQU  28H        ;Software interrupt generated by DOS
ComInt                  EQU  2FH        ;Communications interrupt used by PSPRINT
                                        ;    Multiplex number 0 and 1

;----- Default (and Maximal / Minimal) Print queue length
MinQueueLen             equ  4          ; 4 files worth min
MaxQueueLen             equ  32         ; 32 files worth max.
DefQueueLen             equ  10         ; 10 files worth

;----- Default (and Maximal / Minimal) Print buffer length
MinBufferLen            equ  512        ; set minimum to 512 bytes
MaxBufferLen            equ  1024 * 16  ; maximum is 16 K bytes
DefBufferLen            equ  MinBufferLen ; set default to minimum

;----- Default (and Maximal / Minimal) Time Slice
MinTimeSlice            equ  1          ; set minimum to 1
MaxTimeSlice            equ  255        ; maximum is 255
DefTimeSlice            equ  10         ; set default to 10

;----- Default (and Maximal / Minimal) Busy Tick
MinBusyTick             equ  1          ; set minimum to 1
MaxBusyTick             equ  255        ; maximum is 255
DefBusyTick             equ  MinBusyTick ; set default to minimum

;----- Default (and Maximal / Minimal) Max Tick
MinMaxTick             equ  1          ; set minimum to 1
MaxMaxTick             equ  255        ; maximum is 255
DefMaxTick             equ  2          ; set default to 2

;----- Maximum length of a file name (incl nul)
MaxFileLen              equ  64

; **************** Bogosity Warning *****************
;  Below is the equate that MaxFile SHOULD be.  Since the 3.0/3.1 documentation
;  documents each queue entry as being 64 chars long.  Yes it is known that
;  that causes Print to misbehave on files deep in trees.  But for
;  compatibilities sake, IBM insisted that we change the code back to the
;  way it was.
;MaxFileLen equ  63 + 2 + 12             ; 63 characters as Command.com's
                                        ;         max. path length
                                        ; 2  character for the Drive ext.
                                        ; 12 characters for the max. valid
                                        ;    DOS filename

                                        ;----------------------------------------
                                        ;  definition of the MODE bits
                                        ;     for an extended open
                                        ;----------------------------------------

;                 BITS DEFINED FOR THE MODE WORD
;                       FORMAT = 0WF00000ISSS0AAA
;              Write   DDDDDDDDDDDY3     33   @DDD Access code
;                0 = no commit     3     33             0 = read
;                1 = auto commit   3     33             1 = write
;                                  3     33             2 = read/write
;          Fail action DDDDDDDDDDDDY     33             3 = execute
;            0 = INT 24h                 33             4 = FCB
;            1 = return error            33
;                                        3@DDD  Sharing mode
;                                        3         0 = compatability
;                                        3         1 = deny read/write
;                                        3         2 = deny write
;                                        3         3 = deny read
;                                        3         4 = deny none
;                                      Inherit
;                                        0 = pass handle to child
;                                        1 = no inherit
;
MODE_COM                equ  0100000000000000b ; Auto Commit
MODE_NO24               equ  0010000000000000b ; No 24 - return error
MODE_NOINH              equ  0000000010000000b ; No child procees access
;                                            Sharing mode
MODE_SH_COMP            equ  0000000000000000b ;    0 = compatability
MODE_SH_D_RW            equ  0000000000010000b ;    1 = deny read/write
MODE_SH_D_W             equ  0000000000100000b ;    2 = deny write
MODE_SH_D_R             equ  0000000000110000b ;    3 = deny read
MODE_SH_D_NONE          equ  0000000001000000b ;    4 = deny none
;                                            Access code
MODE_AC_R               equ  0000000000000000b ;    0 = read
MODE_AC_W               equ  0000000000000001b ;    1 = write
MODE_AC_RW              equ  0000000000000010b ;    2 = read/write
MODE_AC_EXE             equ  0000000000000011b ;    3 = execute
MODE_AC_FCB             equ  0000000000000100b ;    4 = FCB

GET_CPSW                equ  3          ; Get state of CPSW
CPSW_on                 equ  1          ; CPSW is active
major_code              equ  0ADh       ; INT 2F PRINT semaphore
minor_code              equ  040h       ; INT 2F PRINTER set and lock CP
                                        ;
                                        ; The Extended Open mode is set as:
                                        ;    Shareing Mode - Compatability
                                        ;    Access        - Read
                                        ;    Inharitance   - yes
                                        ;  -- WARNING ----
                                        ;        These MUST be set this way
                                        ;        in order to do a second open
                                        ;        of a file accross the network

open_mode               equ  MODE_NO24+MODE_SH_COMP+MODE_AC_R                  ;AC013;


ignore_cp               equ  1          ; dont validate CP - it may be different
                                        ;  than CON

openit                  equ  1          ; extended open 'exsists' action
failopen                equ  0          ; extended open 'does not exsist' action

Cap_ASCIIZ              equ  22h        ; Capitalize ASCIIZ string (INT 21 - 65)

;----- Message  related information

 ;================================================
 ; PRINT Message Skeleton File
 ;================================================

;util   PRINT

;class  1

;use   EXTEND19
;use   EXTEND20
;use   EXTEND21
;use   EXTEND22
;use   EXTEND23
;use   EXTEND24
;use   EXTEND25
;use   EXTEND26
;use   EXTEND27
;use   EXTEND28
;use   EXTEND29
;use   EXTEND30
;use   EXTEND31

;class  2
                                         ;1 - Too many operands
                                         ;2 - Required operand missing
;use   PARSE3                            ;3 - Not in switch list provided
                                         ;4 - Not in keyword list provided
;use   PARSE6                            ;6 - Out of range specified
                                         ;7 - Not in value list provided
                                         ;8 - Not in string list provided
;use   PARSE9                            ;9 - Invalid Parameter

;class  A

;def 6  " error reading file",CR,LF,"$"
;def 7  "File not found",CR,LF,"$"
;def 8  CR,LF,LF,"File $"
;def 9  " canceled by operator$"
;def 10 CR,LF,LF,"All files canceled by operator$"
;def 11 "File allocation table bad drive "
;def 12 "A.",CR,LF,"$"
;def 13 "List output is not assigned to a device",CR,LF
;def 14 "Resident part of PRINT installed",CR,LF

;class  B

;use 1  COMMON1
;def 2  CR,LF
;def 15 "Cannot use PRINT - Use NET PRINT",CR,LF
;def 17 "PRINT queue is full",CR,LF
;def 18 "PRINT queue is empty",CR,LF
;def 19 "Access denied",CR,LF
;def 20 "Invalid drive specification",CR,LF
;def 21 "Errors on list device indicate that it",CR,LF
;       "may be off-line. Please check it.",CR,LF

;class  C

;def 22 CR,LF,LF,"  %1 is currently being printed",CR,LF
;def 23 "  %1 is in queue",CR,LF
;use 24 EXTEND2
;def 25 "Pathname too long",CR,LF
;def 26 "File not in PRINT queue",CR,LF

;class  D

;def 27 "Name of list device [PRN]: "

;end
                                        ;--------------------------------------
                                        ; PRINT Equates
                                        ;--------------------------------------

MesSerCLASS equ 0                       ; Message Service class
DOS_error equ 1                         ; DOS extended error
Parse_error equ 2                       ; Parse error
CLASS_A equ 0Ah                         ; PRINT_R message
CLASS_B equ 0Bh                         ; PRINT_T message
CLASS_C equ 0Ch                         ; PRINT_T message with insert
CLASS_D equ 0Dh                         ; PRINT_T message with input buffer where:
CLASS_Util equ 0FFh                     ; PRINT utility message (Class A - D)
buffered_input equ 0Ah                  ; Buffered keyboard input

; CLASS 1

ERR0 equ 19
ERR12 equ 31

; CLASS 2

INVPARM                 equ  9         ; Invalid parameter   (PARSE)

; CLASS A

ERRMEST                 equ  6          ;  error reading file
ErrMesT2                equ  7          ; File not found
CanMes                  equ  8          ; File
CanFilNam               equ  9          ;  canceled by operator
AllCan                  equ  10         ; All files canceled by operator
FATMES                  equ  11         ; File allocation table bad drive
BADDRVM                 equ  12         ; A.
BADMES                  equ  13         ; List output is not assigned to a device
GOODMES                 equ  14         ; Resident part of PRINT installed

MSG_OPTIONS_FIRST	equ	300	; first options help msg nbr
MSG_OPTIONS_LAST        equ     312     ;  and last

; CLASS B

NEXT_LINE               equ   2         ; advance to next line
CONFLICTMES             equ  15         ; Cannot use PRINT - Use NET PRINT
FULLMES                 equ  17         ; PRINT queue is full
NoFils                  equ  18         ; PRINT queue is empty
AccDen                  equ  19         ; Access denied
InvDrvMes               equ  20         ; Invalid drive specification
CNTMES                  equ  21         ; Errors on list device indicate that it
                                        ; may be off-line. Please check it.

; CLASS C

FstMes                  equ  22         ; %1 is currently being printed
SecMes                  equ  23         ; %1 is in queue
BadNameMes              equ  24         ; %1 File not found
NamTMes                 equ  25         ; %1 Pathname too long
BadCanMes               equ  26         ; %1 File not in PRINT queue

; CLASS D

PROMPT                  equ  27         ; Name of list device [PRN]:

DOLLAR                  equ  "$"
Std_Out_Dev             equ  1

;                                       $SALUT (0,41,46,52)

.xlist
.xcref
BREAK                                   MACRO subtitle
                                        SUBTTL subtitle
                                        PAGE
ENDM

SaveReg                                 MACRO reglist ;; push those registers
IRP                                     reg,<reglist>
                                        PUSH reg
ENDM
ENDM
.xcref                                  SaveReg

RestoreReg                              MACRO reglist ;; pop those registers
IRP                                     reg,<reglist>
                                        POP  reg
ENDM
ENDM
;                       $SALUT (4,25,30,41)

                        INCLUDE DEVSYM.INC
                        INCLUDE SYSCALL.INC
                        INCLUDE ERROR.INC
                        INCLUDE FIND.INC
                        include dpl.asm
                        INCLUDE PDB.INC
                        INCLUDE SYSCALL.INC
                        INCLUDE MI.INC
                        INCLUDE SYSMSG.INC
                        include versiona.inc
.list
.cref


                        MSG_UTILNAME <PRINT>


error_busy              EQU  9
error_queue_full        EQU  8
error_name_too_long     EQU  12
get_ea_by_handle equ 2

IF1
                        IF   IBM
;                            %out IBM VERSION
                        ELSE
                            %out MS-DOS VERSION
                        ENDIF
ENDIF

BREAK                   <Segment Definitions>


CodeR                   Segment public para
CodeR                   EndS

Code                    Segment public para
Code                    EndS

Data                    Segment public byte
Data                    EndS

Stack                   Segment Stack
Stack                   Ends

DG                      group Code,Data,Stack


GetDevInfo	equ	4400H
IsDevice?	equ	80H
ACCESS_DENIED 	equ	13H

