home *** CD-ROM | disk | FTP | other *** search
- TITLE TIMERECV
- PAGE 65,132
- ;╔═══════════════════════════════════════════════════════════════════════════╗
- ;║ TIMERECV -- A TSR to Receive Periodically Broadcasted Time ║
- ;║ ║
- ;║ I am the original author of this work and hereby place it into ║
- ;║ the public domain. If your conscience bothers you, please feel ║
- ;║ free to send me $25.00 so that I may provide more such goodies. ║
- ;║ ║
- ;║ NOTE: This source code was written to be assembled with OPTASM. ║
- ;║ Phase errors and near jump problems will surely occur if ║
- ;║ MASM is used. Also, this program must be constructed as ║
- ;║ a .COM file. ║
- ;║ ║
- ;║ Programmer ...... George W. Mays ║
- ;║ Date ............ February, 1993 ║
- ;║ Site ............ 3314 Prince George ║
- ;║ San Antonio, TX 78230 ║
- ;║ Source .......... 80286 Assembler ║
- ;║ System .......... IBM PC/AT Compatible System Under MSDOS ║
- ;║ ║
- ;╚═══════════════════════════════════════════════════════════════════════════╝
- .286
- CSEG SEGMENT PARA PUBLIC 'CODE'
-
- ASSUME CS:CSEG,DS:NOTHING,ES:NOTHING,SS:NOTHING
-
- INCLUDE NETBIOS.INC
-
- ORG 100H ;SKIP TO END OF THE PSP
- ENTPT: JMP INITIALIZE ;COM FILE ENTRY ALWAYS AT 100H
-
- COPYRIGHT DB "TIMERECV V1.0, (C) 1993, G.W. Mays",0Ah,0Dh
- DB "In the Public Domain. Use Freely.",0Ah,0Dh,'$'
-
- ;╒═══════════════════════════════════════════════════════════════════════════╕
- ;│ Program data area. Buffers & Stack at end of resident code. │
- ;╘═══════════════════════════════════════════════════════════════════════════╛
- ;
- ; Data Stuff
- STACKSIZE EQU 0200h ;Our stack size
- VER DW 0 ;DOS version as returned
- DOSMAJOR DB 0 ;DOS major version number
- DOSMINOR DB 0 ;DOS minor version number
- REDIRACTIVE DB 0 ;Redirector flag
- HAVEBUFF DB 0 ;Flag, data has been received
- LASTSTATUS DB 0 ;Completion code from last recv
- NAMENUM DB 0 ;Name Number returned by NB
- TEN DB 10 ;Handy constant 10 decimal
- ZERO DB 0 ;Handy constant 0
- HUNDRED DW 100 ;Handy constant 100 decimal
- SEMAPHORE DW 0FFFFh ;Serialize interrupt processing
- SAVE_SP DW 0 ;Stack save cells
- SAVE_SS DW 0
- BUFF DB " " ;Data buff for NB receive
- DATETIME DB " " ;Copy of above data buffer
- PREV1Ch DD 0 ;Addr of original 1C Handler
- PREV28h DD 0 ;Addr of original 28 Handler
- INDOS DD 0 ;Addr of INDOS flag
- CRIT DD 0 ;Addr of critical error flag
- COUNTER DW 0 ;Tick counter
- NTICKS DW 182 ;Tick count to trip action
- MYNAME DB "TIMECLIENT " ;My NETBIOS name
- HISNAME DB "TIMESERVER " ;Sender NETBIOS name
- CB NCB <> ;Our NCB
-
-
- ;╒═══════════════════════════════════════════════════════════════════════════╕
- ;│ Control is passed here by DOS via INT 0x1C (the Timer interrupt). │
- ;│ │
- ;│ A quick word about stack handling.... We don't want to risk blowing │
- ;│ the stack on the poor guy who gets interrupted. So we use our own │
- ;│ stack. However, that presents a problem since the INT 1C handler │
- ;│ could conceivably be interrupted by INT 28 processing (and vice- │
- ;│ versa). To avoid the conflicts that such a scenario would give rise │
- ;│ to, access to our stack is serialized by use of a semaphore. In this │
- ;│ way, only the first guy to the semaphore gets control of it and hence │
- ;│ implicitly is the one who may use our stack. Those failing to get │
- ;│ control of the semaphore simply say "never mind" and skip their │
- ;│ attempts at processing for one service cycle. │
- ;│ │
- ;╘═══════════════════════════════════════════════════════════════════════════╛
-
- INT_1C PROC FAR
- NOP ; INT 3 ;Debug or NOP
- PUSHF ;Save flags
- PUSH DS
- PUSH AX
- ; Bump & Test Counter
- MOV AX,CS ;Set up addressing
- MOV DS,AX
- MOV AX,COUNTER ;Bump counter
- INC AX
- MOV COUNTER,AX
- CMP AX,NTICKS ;Have we hit "NTICKS"?
- JB RESTORE ;No, restore & return
-
- INC CS:SEMAPHORE ;Enqueue the stack
- JNZ DEQUEUE ;Busy?
- ;No, fall thru...
- ; Time to Examine Broadcasted Date/Time
- CLI ;Set our stack
- MOV CS:SAVE_SP,SP ;Save stack address
- MOV SP,SS ;
- MOV CS:SAVE_SS,SP
- MOV SP,CS
- MOV SS,SP
- MOV SP,OFFSET STACKTOP ;
- STI
- PUSH ES ;Save registers
- PUSH DI
- PUSH SI
- PUSH DX
- PUSH CX
- PUSH BX
- ; The Reason We Came ----------------------------
- MOV AL,00h ;00h means DOS not busy
- CALL DOTIME ;Process date/time received
- ; -----------------------------------------------
- POP BX ;Restore registers
- POP CX
- POP DX
- POP SI
- POP DI
- POP ES
- CLI
- MOV SP,CS:SAVE_SS ;Restore stack address
- MOV SS,SP
- MOV SP,CS:SAVE_SP
- STI
- DEQUEUE:
- DEC CS:SEMAPHORE ;Dequeue
- RESTORE:
- POP AX ;Restore registers
- POP DS
- POPF ;Restore flags and
- JMP CS:[PREV1Ch] ; percolate the call
- INT_1C ENDP
-
-
- ;╒═══════════════════════════════════════════════════════════════════════════╕
- ;│ Control is passed here by DOS via INT 0x28 (the Idle interrupt). │
- ;│ │
- ;│ This routine is a bit different from the timer interrupt service │
- ;│ routine. It does NOT bump the COUNTER; it simply tests to see if │
- ;│ COUNTER has already been bumped past NTICKS by the timer interrupt │
- ;│ service routine. This happens, presumably, when the system is at │
- ;│ the command prompt (i.e. it is "in DOS") and hence we cannot do │
- ;│ our DOS calls from the timer interrupt routine. The timer ticks │
- ;│ continue to count - we just can't call DOS to set the date/time │
- ;│ so we continue to pop in and out waiting for the INDOS flag to │
- ;│ clear, which it won't when you're waiting at the command prompt. │
- ;│ Alas, DOS generates this interrupt (28h) periodically while it is │
- ;│ servicing buffered keyboard input, which, as fate would have it, │
- ;│ is just what COMMAND.COM is waiting on at the command prompt. │
- ;│ │
- ;╘═══════════════════════════════════════════════════════════════════════════╛
-
- INT_28 PROC FAR
- PUSHF ;Save flags
- PUSH DS
- PUSH AX
-
- INC CS:SEMAPHORE ;Enqueue the stack
- JNZ SKIPIT ; busy...
- ; Test Counter
- MOV AX,CS ;Set up addressing
- MOV DS,AX
- MOV AX,COUNTER ;Bump counter
- CMP AX,NTICKS ;Have we hit "NTICKS"?
- JB SKIPIT ;No, restore & return
- ;Yes, fall thru...
- ; Time to Examine Broadcasted Date/Time
- CLI ;Set our stack
- MOV CS:SAVE_SP,SP ;Save stack address
- MOV SP,SS ;
- MOV CS:SAVE_SS,SP
- MOV SP,CS
- MOV SS,SP
- MOV SP,OFFSET STACKTOP ;
- STI
- PUSH ES ;Save registers
- PUSH DI
- PUSH SI
- PUSH DX
- PUSH CX
- PUSH BX
- ; The Reason We Came ----------------------------
- MOV AL,01h ;01h means DOS not busy
- CALL DOTIME ;Process date/time received
- ; -----------------------------------------------
- POP BX ;Restore registers
- POP CX
- POP DX
- POP SI
- POP DI
- POP ES
- CLI
- MOV SP,CS:SAVE_SS ;Restore stack address
- MOV SS,SP
- MOV SP,CS:SAVE_SP
- STI
- SKIPIT:
- DEC CS:SEMAPHORE ;Dequeue
- POP AX ;Restore registers
- POP DS
- POPF ;Restore flags and
- JMP CS:[PREV28h] ; percolate the call
- INT_28 ENDP
-
-
- ;╒═══════════════════════════════════════════════════════════════════════════╕
- ;│ Get date & time from BIOS; pack 'em up & ship 'em out.... │
- ;╘═══════════════════════════════════════════════════════════════════════════╛
-
- DOTIME PROC NEAR
- NOP ; INT 3 ;Debug or NOP
- CMP HAVEBUFF,00h ;Do we have date/time yet?
- JZ BEATFEET ;No, BEATFEET
- LES BX,INDOS ;Did we interrupt DOS?
- CMP AL,BYTE PTR ES:[BX]
- JNE BEATFEET ;Yes, BEATFEET
- LES BX,CRIT ;Critical error handler active?
- CMP BYTE PTR ES:[BX],00h
- JNZ BEATFEET ;Yes, BEATFEET
- ; OK - at this point we have received a date/time broadcast, and we know that
- ; we're not stepping on DOS or the Critical Error Handler.
- CMP LASTSTATUS,00h ;If bad last recv status...
- JNE NEWRECEIVE ;Just crank up a new receive
- CALL VALIDATE ;Validate received data
- JC NEWRECEIVE ;Whoa! Something funky
- ;
- CALL CONVERTDATE ;Good D/T frame, set D/T.
- MOV AH,2Bh
- INT 21h
- CALL CONVERTTIME
- MOV AH,2Dh
- INT 21h
- XOR AX,AX
- MOV COUNTER,AX ;Zero counter
- ;
- NEWRECEIVE:
- CALL CLEARNCB ;Prepare NCB
- CALL BUILDRECEIVE
- MOV HAVEBUFF,00h ;Clear HAVEBUFF flag
- CALL CALLNB ;Call NETBIOS
- BEATFEET:
- RET ;Return
- DOTIME ENDP
-
-
- ;╒═══════════════════════════════════════════════════════════════════════════╕
- ;│ NBPOST Function --- NETBIOS posts us here upon SEND DATAGRAM completion. │
- ;╘═══════════════════════════════════════════════════════════════════════════╛
-
- NBPOST PROC NEAR
- STI ;Reenable interrupts
- PUSH DS ;Save regs
- PUSH ES
- PUSH AX
- PUSH CX
- PUSH DI
- PUSH SI
- MOV AX,CS ;Set ES = DS = CS
- MOV DS,AX
- MOV ES,AX
- MOV AL,CB.NCB_RETCODE ;Tuck away completion status
- MOV LASTSTATUS,AL
- MOV AL,CB.NCB_COMMAND
- MOV HAVEBUFF,AL ;Set HAVEBUFF flag
- MOV CX,16 ;Save data received
- MOV DI,OFFSET DATETIME
- MOV SI,OFFSET BUFF
- CLD
- REP MOVSB
- POP SI
- POP DI
- POP CX
- POP AX ;Restore regs
- POP ES
- POP DS
- IRET ;Return from interrupt
- NBPOST ENDP
-
-
- ;╒═══════════════════════════════════════════════════════════════════════════╕
- ;│ CLEARNCB Function --- Fill the NCB with binary zeroes. │
- ;╘═══════════════════════════════════════════════════════════════════════════╛
-
- CLEARNCB PROC NEAR
- PUSHF ;Save regs & flags
- PUSH ES
- PUSH DI
- PUSH CX
- PUSH AX
- MOV AX,CS
- MOV ES,AX
- MOV DI,OFFSET CB ;Zero the NCB
- MOV CX,NCB_SIZE
- XOR AL,AL
- CLD
- REP STOSB
- POP AX ;Restore regs & flags
- POP CX
- POP DI
- POP ES
- POPF
- RET
- CLEARNCB ENDP
-
-
- ;╒═══════════════════════════════════════════════════════════════════════════╕
- ;│ BUILDRECEIVE Function --- Fill in the NCB for a Receive Datagram │
- ;╘═══════════════════════════════════════════════════════════════════════════╛
-
- BUILDRECEIVE PROC NEAR
- MOV AH,NAMENUM ;Name Number
- MOV CB.NCB_NUM,AH
- MOV CB.NCB_LENGTH,16 ;Length
- MOV AX,CS
- MOV ES,AX
- MOV CB.NCB_BUFF_SEG,AX ;Buffer Address and
- MOV CB.NCB_POST_SEG,AX ; Post Address
- MOV AX,OFFSET BUFF
- MOV CB.NCB_BUFF_OFF,AX
- MOV AX,OFFSET NBPOST
- MOV CB.NCB_POST_OFF,AX
- ;Function Code
- MOV AL,RECEIVEDATAGRAM+NCB_NOWAIT
- MOV CB.NCB_COMMAND,AL
- MOV BX,OFFSET CB ;ES:BX -> NCB
- RET
- BUILDRECEIVE ENDP
-
-
- ;╒═══════════════════════════════════════════════════════════════════════════╕
- ;│ VALIDATE Function --- Validate the D/T buff contents. │
- ;╘═══════════════════════════════════════════════════════════════════════════╛
-
- VALIDATE PROC NEAR
- CMP DATETIME+00h,'D' ;Validate received data
- JNE FUNKY
- CMP DATETIME+01h,'/'
- JNE FUNKY
- CMP DATETIME+02h,'T'
- JNE FUNKY
- CMP DATETIME+03h,00h
- JNE FUNKY
- CMP DATETIME+0Ch,00h
- JNE FUNKY
- CMP DATETIME+0Fh,00h
- JNE FUNKY
- MOV AH,DATETIME+04h ;Form checksum
- MOV AL,DATETIME+05h
- MOV BH,DATETIME+06h
- MOV BL,DATETIME+07h
- ADD AX,BX
- MOV BH,DATETIME+08h
- MOV BL,DATETIME+09h
- ADD AX,BX
- MOV BH,DATETIME+0Ah
- MOV BL,DATETIME+0Bh
- ADD AX,BX
- CMP AX,WORD PTR DATETIME+0Dh
- JNE FUNKY
- CLC ;Happy stuff, clear carry
- RET
- FUNKY:
- STC ;Invalide stuff, set carry
- RET
- VALIDATE ENDP
-
-
- ;╒═══════════════════════════════════════════════════════════════════════════╕
- ;│ CONVERTTIME Function --- Take TIME from D/T buff, Convert for DOS call. │
- ;╘═══════════════════════════════════════════════════════════════════════════╛
-
- CONVERTTIME PROC NEAR
- MOV AL,DATETIME+08h ;Hour
- SHR AL,4
- MUL TEN
- MOV AH,DATETIME+08h
- AND AH,0Fh
- ADD AL,AH
- MOV CH,AL
- MOV AL,DATETIME+09h ;Minutes
- SHR AL,4
- MUL TEN
- MOV AH,DATETIME+09h
- AND AH,0Fh
- ADD AL,AH
- MOV CL,AL
- MOV AL,DATETIME+0Ah ;Seconds
- SHR AL,4
- MUL TEN
- MOV AH,DATETIME+0Ah
- AND AH,0Fh
- ADD AL,AH
- MOV DH,AL
- MOV DL,ZERO
- RET
- CONVERTTIME ENDP
-
-
- ;╒═══════════════════════════════════════════════════════════════════════════╕
- ;│ CONVERTDATE Function --- Take DATE from D/T buff, Convert for DOS call. │
- ;╘═══════════════════════════════════════════════════════════════════════════╛
-
- CONVERTDATE PROC NEAR
- MOV AL,DATETIME+04h ;Century
- SHR AL,4
- MUL TEN
- MOV AH,DATETIME+04h
- AND AH,0Fh
- ADD AL,AH
- XOR AH,AH
- MUL HUNDRED
- MOV CX,AX
- MOV AL,DATETIME+05h ;Year
- SHR AL,4
- MUL TEN
- MOV AH,DATETIME+05h
- AND AH,0Fh
- ADD AL,AH
- XOR AH,AH
- ADD CX,AX
- MOV AL,DATETIME+06h ;Month
- SHR AL,4
- MUL TEN
- MOV AH,DATETIME+06h
- AND AH,0Fh
- ADD AL,AH
- MOV DH,AL
- MOV AL,DATETIME+07h ;Day
- SHR AL,4
- MUL TEN
- MOV AH,DATETIME+07h
- AND AH,0Fh
- ADD AL,AH
- MOV DL,AL
- RET
- CONVERTDATE ENDP
-
-
- ;╔═══════════════════════════════════════════════════════════════════════════╗
- ;║ CALL NETBIOS - This routine is called to send an NCB to the NETBIOS. ║
- ;║ If a redirector is loaded use int 2Ah otherwise use int 5Ch. ║
- ;║ ║
- ;║ On entry: ║
- ;║ ES:BX addr of NCB ║
- ;║ On exit: ║
- ;║ AX return code ║
- ;╚═══════════════════════════════════════════════════════════════════════════╝
-
- CALLNB PROC NEAR
- CMP REDIRACTIVE,0 ;Is a redirector active?
- JNE THRUREDIR
- INT 5Ch
- RET
- THRUREDIR:
- MOV AX,0400h
- INT 2Ah
- RET
- CALLNB ENDP
-
-
- ;╞═══════════════════════════════════════════════════════════════════════════╡
- PC = $ ;End of Code, OFFSET -> PC
-
- STACKBOT = PC ;Stacks starts after code
- PC = PC + STACKSIZE ; and is STACKSIZE bytes long
- STACKTOP = PC ;STACKTOP1 here since stack
- ; grows downward
-
- LASTBYTE = PC ;LASTBYTE in resident code
-
-
- ;╔═══════════════════════════════════════════════════════════════════════════╗
- ;║ Initialization Procedure ║
- ;╚═══════════════════════════════════════════════════════════════════════════╝
-
- INITIALIZE PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:CSEG,SS:CSEG ;Set by loader.
- NOP ; INT 3 ;Debug or NOP
- MOV AX,CS
- MOV DS,AX
- MOV AH,9
- MOV DX,OFFSET COPYRIGHT
- INT 21H
- ;╒═══════════════════════════════════════════════════════════════════════════╕
- ;│ Pick up parameters from the command line (options or group name suffix) │
- ;╘═══════════════════════════════════════════════════════════════════════════╛
- GETPARMS: ;Command line parms reside in
- PUSH 0080h ; the PSP @ offset 0x80
- CALL GETOPT ;Process parms
- OR AH,AH
- JZ SUCCESS
- PUSH OFFSET CS:ABANDON ;Abend
- CALL FAILPROG
- SUCCESS:
- OR AL,AL ;Check result
- JZ GOTNAME ;ZERO, means no suffix char
- MOV BX,OFFSET MYNAME ;BX->MYNAME
- MOV CX,16 ;CX= length of MYNAME (16)
- JMP SPACELOOP ;Begin look for first blank
- NEXTINNAME:
- DEC CX ;Decrement count
- JZ NOBLANKS ;If it goes to 0, no find!
- INC BX ;Bump pointer into MYNAME
- SPACELOOP:
- CMP BYTE PTR [BX],' ' ;Is the char blank?
- JNE NEXTINNAME ;NO, loop back to next char
- JMP BLANKFOUND ;YES, alright! Go plug suffix
- NOBLANKS:
- PUSH OFFSET CS:NAMETOOLONG ;MYNAME contains no blanks!
- CALL FAILPROG ;Die
- BLANKFOUND:
- MOV BYTE PTR [BX],AL ;Put suffix on group name
- ;╒═══════════════════════════════════════════════════════════════════════════╕
- ;│ Check to see that NETBIOS is active. Check for a redirector. │
- ;╘═══════════════════════════════════════════════════════════════════════════╛
- GOTNAME:
- CALL CHECKDOS ;DOS better be 3.1 or greater
- CALL CHKNETB ;See if NETBIOS is in here
- JNC NBTHERE
- PUSH OFFSET CS:NASTYGRAM ;Whoa! No NETBIOS!
- CALL FAILPROG ;Die.
- NBTHERE:
- MOV AH,0
- INT 2Ah ;Check for redirector
- MOV REDIRACTIVE,AH
- ;╒═══════════════════════════════════════════════════════════════════════════╕
- ;│ Add our name to the NETBIOS name table. │
- ;╘═══════════════════════════════════════════════════════════════════════════╛
- CALL CLEARNCB ;Zero the NCB first
- MOV AL,ADDGROUPNAME ;Fill in NCB fields
- MOV CB.NCB_COMMAND,AL
- MOV DI,OFFSET CB.NCB_NAME
- MOV SI,OFFSET MYNAME
- MOV CX,16
- CLD
- REP MOVSB
- MOV BX,OFFSET CB
- CALL CALLNB ;Call NETBIOS
- MOV AL,CB.NCB_RETCODE
- OR AL,AL ;Check status
- JZ ADDWASOK
- PUSH OFFSET CS:ADDFAILED ;Whoa! It didn't work.
- CALL FAILPROG ;Die.
- ADDWASOK:
- MOV AL,CB.NCB_NUM ;Grab "name number" returned
- MOV NAMENUM,AL ; and save it for use later.
- ;╒═══════════════════════════════════════════════════════════════════════════╕
- ;│ Get the current address of Int 1C and save (it's the timer interrupt) │
- ;╘═══════════════════════════════════════════════════════════════════════════╛
- MOV AH,35h ;Get Int vector
- MOV AL,1Ch ;For this Int
- INT 21h ;Result in ES:BX
- ASSUME ES:NOTHING
- MOV WORD PTR PREV1Ch[0],BX ;offset
- MOV WORD PTR PREV1Ch[2],ES ;segment
- ;╒═══════════════════════════════════════════════════════════════════════════╕
- ;│ Get the current address of Int 28 and save (it's the idle interrupt) │
- ;╘═══════════════════════════════════════════════════════════════════════════╛
- MOV AH,35h ;Get Int vector
- MOV AL,28h ;For this Int
- INT 21h ;Result in ES:BX
- MOV WORD PTR PREV28h[0],BX ;offset
- MOV WORD PTR PREV28h[2],ES ;segment
- ;╒═══════════════════════════════════════════════════════════════════════════╕
- ;│ Free our environment segment to save a little space. │
- ;╘═══════════════════════════════════════════════════════════════════════════╛
- PUSH DS
- MOV AH,62h ;Get PSP address
- INT 21h ;
- MOV DS,BX
- MOV ES,DS:2Ch ;ES<-Env Seg Addr
- MOV AH,49h ;Free memory alloc
- INT 21h ;
- POP DS
- ;╒═══════════════════════════════════════════════════════════════════════════╕
- ;│ Get the address of the INDOS flag. │
- ;╘═══════════════════════════════════════════════════════════════════════════╛
- MOV AH,34h ;Get InDos function
- INT 21h ; from DOS
- MOV WORD PTR INDOS[0],BX
- MOV WORD PTR INDOS[2],ES
- PUSH DS
- MOV AX,5D06h ;Get Critical Error function
- INT 21h
- MOV WORD PTR CS:CRIT[0],SI
- MOV WORD PTR CS:CRIT[2],DS
- POP DS
- ;╒═══════════════════════════════════════════════════════════════════════════╕
- ;│ Hang a RECEIVE DATAGRAM on the line. │
- ;╘═══════════════════════════════════════════════════════════════════════════╛
- TRYTORECEIVE:
- CALL CLEARNCB ;Zero the NCB first
- CALL BUILDRECEIVE
- MOV AL,RECEIVEDATAGRAM+NCB_NOWAIT
- MOV CB.NCB_COMMAND,AL
- MOV HAVEBUFF,AL
- CALL CALLNB ;Call NETBIOS
- POLLNET:
- MOV AL,CB.NCB_CMD_CPLT ;Poll for completion
- CMP AL,0FFh ;Still "in progress"?
- JNE GOTMSG ;NO, it finished
- MOV AH,01h ;YES, Test keyboard
- INT 16h ;Via the BIOS
- JZ POLLNET ;Nothing pending, loop back
- MOV DI,OFFSET FUNKYNCB ;Keystroke detected...
- MOV CX,NCB_SIZE ;Zero the alternate NCB
- XOR AL,AL
- CLD
- REP STOSB
- MOV BX,OFFSET FUNKYNCB
- MOV AL,CANCELCMD ;Cancel the outstanding
- MOV FUNKYNCB.NCB_COMMAND,AL ; RECEIVEDATAGRAM command
- MOV FUNKYNCB.NCB_BUFF_OFF,OFFSET CB
- MOV FUNKYNCB.NCB_BUFF_SEG,DS
- MOV AH,09h
- MOV DX,OFFSET CANCELLING
- INT 21h
- CALL CALLNB
- PUSH OFFSET CS:KEYSTROKE
- CALL FAILPROG
- GOTMSG:
- MOV AL,CB.NCB_RETCODE
- OR AL,AL ;Check status
- JZ REQWASOK
- PUSH OFFSET CS:REQFAILED ;Whoa! It didn't work.
- CALL FAILPROG ;Die.
- REQWASOK:
- PUSH CS
- POP ES
- MOV CX,16 ;Save data received
- MOV DI,OFFSET DATETIME
- MOV SI,OFFSET BUFF
- CLD
- REP MOVSB
- CALL VALIDATE ;Validate received data
- JC TRYTORECEIVE
- ;
- MOV CH,DATETIME+04h ;Set date in CMOS
- MOV CL,DATETIME+05h
- MOV DH,DATETIME+06h
- MOV DL,DATETIME+07h
- MOV AH,05h
- INT 1Ah
- CALL CONVERTDATE ;Set date in DOS
- MOV AH,2Bh
- INT 21h
- MOV CH,DATETIME+08h ;Set time in CMOS
- MOV CL,DATETIME+09h
- MOV DH,DATETIME+0Ah
- MOV DL,DATETIME+0Bh
- MOV AH,03h
- INT 1Ah
- CALL CONVERTTIME ;Set time in DOS
- MOV AH,2Dh
- INT 21h
- XOR AX,AX
- MOV COUNTER,AX ;Zero counter
- MOV LASTSTATUS,0FFh
- ;╒═══════════════════════════════════════════════════════════════════════════╕
- ;│ Plug ourselves into DOS Idle Interrupt (Interrupt 28). │
- ;╘═══════════════════════════════════════════════════════════════════════════╛
- PUSH DS
- PUSH CS
- POP DS
- MOV DX,OFFSET INT_28 ;INT_28 is ISR entry
- MOV AH,25h ;Set Interrupt vector
- MOV AL,28h ; 28h.
- INT 21h ;
- POP DS
- ;╒═══════════════════════════════════════════════════════════════════════════╕
- ;│ Plug ourselves into DOS Timer Interrupt (Interrupt 1C). │
- ;╘═══════════════════════════════════════════════════════════════════════════╛
- PUSH DS
- PUSH CS
- POP DS
- MOV DX,OFFSET INT_1C ;INT_1C is ISR entry
- MOV AH,25h ;Set Interrupt vector
- MOV AL,1Ch ; 1Ch.
- INT 21h ;
- POP DS
- ;╒═══════════════════════════════════════════════════════════════════════════╕
- ;│ Terminate and stay resident. │
- ;╘═══════════════════════════════════════════════════════════════════════════╛
- MOV AX,3100H
- MOV DX,(OFFSET LASTBYTE - OFFSET CSEG + 15) SHR 4
- INT 21H
-
- INITIALIZE ENDP
-
- ABANDON DB "TIMERECV did NOT remain resident",0Ah,0Dh,'$'
- NASTYGRAM DB "NETBIOS is NOT active on this system",0Ah,0Dh,'$'
- ADDFAILED DB "NETBIOS Add Name failed",0Ah,0Dh,'$'
- REQFAILED DB "NETBIOS Recieve Datagram failed",0Ah,0Dh,'$'
- NAMETOOLONG DB "NETBIOS Name too long to add suffix",0Ah,0Dh,'$'
- CANCELLING DB "Cancelling Receive Datagram request",0Ah,0Dh,'$'
- KEYSTROKE DB "Initialization terminated by keystroke",0Ah,0Dh,'$'
-
-
- ;╒═══════════════════════════════════════════════════════════════════════════╕
- ;│ FAILPROG --- Display string (terminated with "$") on console, then │
- ;│ exit the program with nonzero condition code. │
- ;╘═══════════════════════════════════════════════════════════════════════════╛
-
- FAILPROG PROC NEAR
- PUSH SP
- POP BX
- MOV DX,WORD PTR [BX+2] ;Get offset of string
- PUSH CS ;Assume offset w/in this code
- POP DS
- MOV AH,09h ;Display String function
- INT 21h ; of DOS
- MOV AH,4Ch ;Terminate a Process func
- MOV AL,01h ; of DOS
- INT 21h ;
- INT 20h ;Just to be safe....
- FAILPROG ENDP
-
-
- ;╒═══════════════════════════════════════════════════════════════════════════╕
- ;│ CHECKDOS --- Get the DOS version. Bomb if < DOS 3.10. │
- ;╘═══════════════════════════════════════════════════════════════════════════╛
-
- CHECKDOS PROC NEAR
- PUSH BP ;Save register(s)
- MOV BP,SP
- PUSH CX
- PUSH BX
- PUSH AX
- MOV AH,30h ;Get DOS Version
- INT 21h
- MOV CS:VER,AX ;Save results
- MOV CS:DOSMAJOR,AL
- MOV CS:DOSMINOR,AH
- CMP AL,3 ;Check major level
- JL VERCHOKE ;<3, VERCHOKE
- JNE VEROK ;>3, VEROK
- CMP AH,1 ;Check minor level for 3.x
- JGE VEROK ;VEROK if 3.1 or better
- VERCHOKE:
- PUSH OFFSET CS:VERMSG ;Push offset of nastygram
- CALL FAILPROG ;And kiss off....
- VEROK:
- POP AX ;Restore registers
- POP BX
- POP CX
- MOV SP,BP ;Restore stack
- POP BP
- RET ;Return to caller
- CHECKDOS ENDP
-
- VERMSG DB "DOS Version MUST be 3.1 or greater$"
-
-
- ;╔═══════════════════════════════════════════════════════════════════════════╗
- ;║ Check For NETBIOS Installed in System ║
- ;║ Return with CARRY SET if NOT installed ║
- ;╚═══════════════════════════════════════════════════════════════════════════╝
-
- CHKNETB PROC NEAR
- MOV AH,35h ;Who's plugged into INT 5C?
- MOV AL,5Ch
- INT 21h
- MOV AX,ES
- CMP AX,0000h
- JE NOTKOSHER
- CMP AX,0F000h
- JE NOTKOSHER
- ITSPLUGGED:
- PUSH CS
- POP ES
- MOV DI,OFFSET FUNKYNCB ;Zero the NCB
- MOV CX,NCB_SIZE
- XOR AL,AL
- CLD
- REP STOSB
- MOV BX,OFFSET FUNKYNCB
- MOV AL,0FFh
- MOV FUNKYNCB.NCB_COMMAND,AL
- MOV AL,00h
- INT 5Ch ;Check it.
- MOV AL,FUNKYNCB.NCB_RETCODE
- CMP AL,03h ;Zero ?
- JNE NOTKOSHER ;Yes, so not installed.
- CLC
- RET
- NOTKOSHER:
- STC
- RET
-
- FUNKYNCB NCB <> ;NCB with FUNKY command
- ; to test things out
- CHKNETB ENDP
-
-
- ;╒═══════════════════════════════════════════════════════════════════════════╕
- ;│ GETOPT Function --- Get options or NETBIOS group name to use │
- ;╘═══════════════════════════════════════════════════════════════════════════╛
-
- GETOPT PROC NEAR
- ENTER WORD PTR 0,0
- ; Stack frame STRING offset +4
- MOV AL,BYTE PTR [BP+4] ;STRING
- MOV BL,AL ;BX points to parm line
- XOR BH,BH
- MOV AL,BYTE PTR [BX] ;CX contains line length
- MOV CL,AL
- XOR CH,CH
- INC BX ;BX += 1
- JMP SHORT PASSONE ;Find 1st nonblank char
- BLANKLOOP:
- MOV AX,CX ;N
- DEC CX ;N
- OR AX,AX
- JE ENDLOOP
- INC BX ;P
- PASSONE:
- CMP BYTE PTR [BX],' '
- JE BLANKLOOP
- ENDLOOP:
- CMP CX,0 ;N
- JNE FIND
- XOR AX,AX ;Return a ZERO which
- LEAVE ; indicates "no suffix"
- RET
- FIND:
- MOV AL,BYTE PTR [BX]
- CMP AL,'/'
- JE ITSASLASH
- CMP AL,'?'
- JNE SUFFIX
- CALL SHOWHELP
- JMP OPTEXIT
- ; Seems to be the NETBIOS name suffix to use
- SUFFIX:
- PUSH AX
- CALL TOUPPER
- ADD SP,2
- MOV BYTE PTR [BX],AL
- CMP AL,'0' ;Validate the suffix
- JL BADCHAR ; character. 0-9 or A-Z.
- CMP AL,'9'
- JLE CHAROK
- CMP AL,'A'
- JL BADCHAR
- CMP AL,'Z'
- JLE CHAROK
- BADCHAR:
- PUSH OFFSET CS:INVALIDMSG ;Say "Bad Suffix Char..."
- CALL FAILPROG
- CHAROK:
- XOR AH,AH
- MOV AL,BYTE PTR [BX]
- LEAVE
- RET
- ITSASLASH:
- INC BX ;Look at option char
- MOV AL,BYTE PTR [BX] ;Make it upper case
- CMP AL,'?'
- JNE NOTHELP
- CALL SHOWHELP
- JMP OPTEXIT
- NOTHELP:
- PUSH AX
- CALL TOUPPER
- ADD SP,2
- CMP AL,'U' ;/U ?
- JE DOUNLOAD ;YES, go do unload
- CALL SHOWHELP ;NO, show help
- JMP OPTEXIT ; and then exit.
- DOUNLOAD:
- CALL UNLOAD ;Invoke unload logic
- OPTEXIT:
- MOV AH,01h
- XOR AL,AL ;Return a ZERO which
- LEAVE ; indicates "no suffix"
- RET
- NOP
- GETOPT ENDP
-
- INVALIDMSG DB "Invalid name suffix character.",0Ah,0Dh,'$'
-
- ;╔═══════════════════════════════════════════════════════════════════════════╗
- ;║ Show the Help Text ║
- ;╚═══════════════════════════════════════════════════════════════════════════╝
-
- SHOWHELP PROC NEAR
- MOV DX,OFFSET CS:HELPLINE ;Get offset of help string
- MOV AH,09h ;Display String function
- INT 21h ; of DOS
- RET
- SHOWHELP ENDP
-
- HELPLINE DB " To LOAD-> TIMERECV <x> where x=name suffix"
- DB 0Ah,0Dh
- DB "Or To UNLOAD-> TIMERECV /U"
- DB 0Ah,0Dh,'$'
-
- ;╔═══════════════════════════════════════════════════════════════════════════╗
- ;║ Request TIMERECV Unload From Memory ║
- ;╚═══════════════════════════════════════════════════════════════════════════╝
-
- UNLOAD PROC NEAR
- PUSH CS:OFFSET CS:NOTYET ;Get offset of "Not yet..."
- CALL FAILPROG ;Die.
- UNLOAD ENDP
-
- NOTYET: DB "Unload of TIMERECV not yet supported",0Ah,0Dh,'$'
-
- ;╔═══════════════════════════════════════════════════════════════════════════╗
- ;║ Convert Character in AL to Upper Case ASCII ║
- ;╚═══════════════════════════════════════════════════════════════════════════╝
-
- TOUPPER PROC NEAR
- CMP AL,'a' ;LESS THAN 'a'?
- JL ITSOK ;YES, DOESN'T NEED CONVERTING
- CMP AL,'z' ;NO, GREATER THAN 'z'?
- JG ITSOK ;YES, DOESN'T NEED CONVERTING
- SUB AL,32 ;NO, IT'S BETWEEN 'a' & 'z'
- ITSOK: RET ;Return to caller
- TOUPPER ENDP
-
- CSEG ENDS
-
- END ENTPT
-
- ;╔═══════════════════════════════════════════════════════════════════════════╗
- ;║ End of Program --- TIMERECV ║
- ;╚═══════════════════════════════════════════════════════════════════════════╝
-