; ; srvclock.asm - From PC Magazine . August '87, pp468-470 ; ; A background task for use on any AT running NETBIOS. This routine will ; get and send its date and time information to any node executing ; NETCLOCK.EXE. NETCLOCK.EXE then installs the received date and time in the ; node. Since SRVCLOCK.EXE reads th AT's CMOS RAM directly, it works only on ; ATs ; cr equ 0dh lf equ 0ah cseg segment para public 'code' net proc far assume cs:cseg,ds:netdata,ss:stack,es:netdata push ds xor ax,ax push ax mov ax,netdata mov ds,ax mov es,ax ; ; dealocate block containing environment ; mov ah,62h ; get program segment prefix int 21h ; address push ds ; save old data segment mov ds,bx ; mov PSP segment to DS - rsb mov es,ds:02ch ; move the block address mov ah,49h ; containing the enviroment int 21h ; and deallocate it pop ds ; restore DS mov ax,ds ; mov es,ax ; and ES ; ; netbios add name call (waits for completion) ; add_name: mov command,30h ; Command 30H adds a neme mov bx,offset mcb ; point BX at MCB int 5ch ; call netbios cmp retcode,00h ; check for success je prep_res ; prepare for TSR if good mov dx,offset add_err ; else write errro message jmp error ; name that was not successful prep_res: mov dx,30h ; number of paragraphs for ; terminate and stay resident ; ; do netbios listen posting into get_clock, then tsr ; mov command,91h ; Move listen to MCB no wait mov post@,offset get_clock ; and post at get clock mov post@+2,cs ; routine mov bx,offset mcb ; point BX to MCB int 5ch ; netbios call cmp al,00h ; check for good return je go_res ; if good, make resident mov dx,offset lsn_err ; else write error jmp error ; go_res: mov ah,31h ; DOS terminate and stay int 21h ; resident ; ; this listen is returned to after a opost into get_clock ; listen: mov command,91h ; Move listen to MCB mov post@,offset get_clock ; also posts to clock mov post@+2,cs ; routine mov bx,offset mcb ; point BX to block int 5ch ; NETBIOS call sti ; restore interrupts iret ; and return ; ; get date and time to send to requesting node ; get_clock: cli ; cut off interrupts mov ax,es ; ES is restored by network mov ds,ax ; use to restore DS xor ax,ax ; clear AX mov al,09 ; 09 = Year out 70h,al ; Real time clock at 70H in al,71h ; returns at 71H call bcd2bin ; convert to binary add ax,76ch ; add 1900 decimal, only works ; until 1999 mov year,ax ; load buffer with year xor ax,ax ; get month mov al,08 ; out 70h,al ; in al,71h ; call bcd2bin ; mov month,al ; xor ax,ax ; get date of month mov al,07 ; out 70h,al ; in al,71h ; call bcd2bin ; mov day,al ; xor ax,ax ; get hours mov al,04 ; out 70h,al ; in al,71h ; call bcd2bin ; mov hours,al ; xor ax,ax ; get minutes mov al,02 ; out 70h,al ; in al,71h ; call bcd2bin ; mov minutes,al ; xor ax,ax ; get seconds mov al,00 ; out 70h,al ; in al,71h ; call bcd2bin ; mov seconds,al ; ; ; send clock data to requesting node using a netbios send ; mov buffer@,offset clock ; point to clock data area mov buffer@+2,ds ; insure correct segment mov buf_length,8 ; clock takes 8 byees mov command,14h ; 14H=send and wait mov bx,offset mcb ; point to MCB int 5ch ; NETBIOS hangup: mov command,12h ; 12H=hangup mov bx,offset mcb ; point BX int 5ch ; NETBIOS call mov si,offset fill_name ; fill name=listen any mov di,offset callname ; move to call name mov cx,0fh ; names are 16 bytes repnz movsb ; jmp listen ; back to waiting for call ; ; error message, failed before coming resident ; error: mov ah,09h ; display error message int 21h ; if routine fails before ; becoming resident mov command,12h ; hang up session if any mov bx,offset mcb ; point BX int 5ch ; NETBIOS call quit: ret ; net endp ; ; procedure to convert time as delivered from CMOS clodk (binary coded decimal) ; to binary (as used by DOS function calls and NETCLOCK) (returns in AL) ; bcd2bin proc near push ax ; save contents and al,0f0h ; clear out low nibble shr al,1 ; divide by 16 shr al,1 ; so that hi nibble shr al,1 ; is now in shr al,1 ; lo position mov bl,al ; hold in al shl al,1 ; multiply by ten, two here shl al,1 ; four shl al,1 ; eight add al,bl ; nine add al,bl ; ten pop bx ; get previous AX contents and bl,0fh ; clear out hi nibble add al,bl ; add to total ret bcd2bin endp cseg ends ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; message data ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; netdata segment para public 'data' add_err db cr,lf,'"add name" command failed',cr,lf,'$' lsn_err db cr,lf,'"listen" command failed',cr,lf,'$' fill_name db '* ' ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; message control area ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; clock equ $ year dw 0000h month db 00h day db 00h hours db 00h minutes db 00h seconds db 00h hundredths db 00h ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; message control block ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mcb equ $ command db 00h retcode db 00h lsn db 00h num db 00h buffer@ dw 0000h dw 0000h buf_length dw 0000h callname db '* ' our_name db 'srv_clock ' rto db 00h sto db 00h post@ dw 0000h dw 0000h adapter_num db 00h cmd_stat db 00h reserve db 14 dup(0) netdata ends stack segment para stack 'stack' db 32 dup('stack ') stack ends end