home *** CD-ROM | disk | FTP | other *** search
- page 66,80
- TITLE REBOOT.COM reboots the system
- .model small ; really tiny, but AT Segs freak MASM 6.0
-
- comment √
- Version 2.1 1991/09/22 by Roedy Green
- works with MASM 5.0, 6.0 and Optasm
- MASM 6.0 will not allow /AT or /TINY. Must use EXE2BIN to do the
- conversion of a EXE to COM file.
-
- USAGE:
-
- for a warm boot (no ram test):
- Reboot
- Reboot /W
- Reboot /Warm
-
- for cold boot (with ram test):
- Reboot /C
- Reboot /Cold
-
- Version 2.1
- - fast reboot in DESQ if there is only one window open.
- - now uses DVAPI.INC -- DESQ api interface.
-
- Version 2.0
- - improved DESQview Awareness
- - Windows 3.0 enhanced awareness
-
- Version 1.9
- - added DESQview Awareness
-
- Version 1.8
- - added clear of all serial ports to stop interrupts during reboot
- - mice or modems could interfere.
-
- Version 1.7
- - added Disk Reset
-
- Version 1.6
- - added both Warm and Cold boot options.
-
- √ ; end of comment
-
- include D:\DV\dvapi.inc ; DESQ macros
- ; part of DESQ Application Programmer Interface
-
- BIOSDATA segment AT 40h ; dummy segment in low RAM
- org 0h
- BIOSComAddrs dw ? ; 4 words of COM1: .. COM4:
- dw ? ; device addresses
- dw ?
- dw ?
- org 72h
- BIOSWarmFlag dw ?
- BIOSDATA ends
-
- ROMBIOS segment AT 0f000h ; dummy segment inside ROM BIOS
- org 0fff0h
- BIOSReset label far ; reset code at FFFF:0000
- ; better represented as F000:FFF0
- org 0fffEh
- BIOSMachineId db ? ; BIOS machine type code
- ROMBIOS ends
-
- CODE segment public
-
- DATA segment
- DATA ends
-
- cgroup group Code,Data
- assume cs:cgroup,ss:cgroup,ds:cgroup,es:cgroup
- org 100h
- ;==========================
-
- Start proc far
- lea dx,BannerMsg ; display banner
- Call Say
-
- call Parse ; parse the command line
-
- call Analyze ; analyze the /parameter
-
- call DiskReset ; Make DOS flush the buffers
-
-
- call Breath ; wait one breath
- ; to give the world time to settle
- ; and allow time to admire the banner.
- ; interrupts are still on to allow windup.
-
- Call BootDESQ ; reboot DESQ if needed
-
- Call BootWIN3E ; reboot Windows 3 enhanced mode if needed
- ; Can't do this with DESQ or Windows or
- ; else mouse would die
-
- call KillComs ; kill interrupts on all com ports
-
- Call Boot ; jump to BIOS reset
-
- ; Will not come back.
-
-
- ;==============================================================
- ; V A R I A B L E S
-
- ; We put variables in this odd place so that MASM will not get
- ; phase errors. It cannot handle forward references well.
-
- QuitTime DD 0 ; time in ticks to quit waiting
-
- MyWarmFlag DW 01234h ; 1234h if warm boot
- ; 0 if cold boot
-
-
- BannerMsg DB '░▒▓█ Reboot 2.1 █▓▒░',13d,10d
- DB 13d,10d
- DB 'Copyright (c) 1990 Roedy Green Canadian Mind Products',13,10
- DB 'May be freely distributed and used for any purpose except military.',13,10,'$'
-
- Usage db 'Error in command line.',13,10
- db 'Try Reboot /W or plain Reboot for a warm boot or Reboot /C for a cold boot.',13,10,'$'
-
- DESQMsg db 13,10
- db 'DESQview Active. Close all other windows then reboot with Ctrl-Shift-Del.',13,10,'$'
-
- WIN3EMsg db 13,10
- db 'Windows 3 enhanced mode Active.',13,10
- db 'Use Ctrl-Esc and close all other tasks then reboot with Ctrl-Alt-Del.',13,10,'$'
-
- ;===============================================================
-
- Say Proc
- ; on entry DX points to a string to display
- MOV AH,9
- Int 21h
- ret
- Say EndP
-
- ;===============================================================
-
- MLeading PROC Near
- ; on entry BX is addr of string, CX its length
- ; trims off any leading blanks, leaving result in BX CX
- ; length may also be 0 or 1, but not -ve
- ; If the entire string is blank the result is the null string
- mov di,bx
- mov al,20H ; AL = blank -- the search char
- jcxz mleading2 ; jump if null string
- repe scasb ; scan ES:DI forwards till hit non blank
- ; DI points just after it (wrap ok)
- ; cx IS ONE TOO SMALL, OR 0 IF NONE FOUND
- je mleading1 ; jump if entire string was blank
- inc cx ; CX is length of remainder of string
- mleading1:
- dec di ; DI points to non-blank
- mleading2:
- mov bx,di ; put address back
- ret
- MLeading ENDP
-
- ;========================================
-
- MTrailing PROC Near
- ; on entry BX is addr of string, CX its length
- ; trims off any trailing blanks, leaving result in BX CX
- ; length may also be 0 or 1, but not -ve
- ; If the entire string is blank the result is the null string
- mov di,bx
- add di,cx ; calc addr last char in string
- dec di
- mov al,20H ; AL = blank -- the search char
- jcxz mtrailing1 ; jump if null string
- std
- repe scasb ; scan ES:DI backwards till hit non blank
- ; DI points just ahead of it (wrap ok)
- ; CX is one too small, or 0 if none found
- cld
- je mtrailing1 ; jump if whole string was blank
- inc cx
- mtrailing1:
- ret
- MTrailing ENDP
-
- ;========================================
-
- Parse PROC NEAR
- ; Parse the command line to remove lead/trail blanks
- ;
- ; sample inputs
- ; Reboot /Cold
- ; Reboot /W
- ; Reboot
- ;
- ; When Done DS:BX points to start of string.
- ; CX counts bytes in string
- ; counted string at HEX 80 PSP
- ; contains command line.
- ; Preceeded by unwanted spaces.
- ; possibly followed by unwanted spaces.
- xor ch,ch
- mov cl,ds:80H
- mov bx,81H
- call Mleading ; get rid of leading blanks
- call MTrailing ; get rid of trailing blanks
- ret
- Parse ENDP
-
- ;======================================
-
- Analyze PROC NEAR
- ; analyses the /C or /W parameter
- ; On entry DS:BX points to start of string.
- ; CX counts bytes in string
- ; lead/trail spaces are gone.
-
- jcxz AnalDone ; was no /parm, treat as warm
- cmp cx,2
- jl BadCmd ; kick out plain /
- mov ax,[bx] ; get chars AL<-/ AH<-C
- cmp al,'/' ; make sure first char is /
- jne BadCmd
- mov al,ah
- call ToUc
- cmp al,'C'
- je WasCold
- cmp al,'W'
- je WasWarm
- BadCmd: LEA dx,Usage
- Call Say
- Jmp Abort
- WasCold:
- Mov MyWarmFlag,0
- WasWarm:
- AnalDone:
- RET
- Analyze ENDP
-
- ;======================================
-
- ToUC PROC NEAR
- ; converts char in AL to upper case
- cmp al,'a'
- jb FineAsIs
- cmp al,'z'
- ja FineAsIs
- sub al,20H ; convert a to A
- FineAsIs:
- ret
- ToUc ENDP
-
- ;======================================
-
- KillComs Proc Near
-
- ; Clear any serial ports, so they will stop interrupting
- ; i.e. clear the modem control registers
- ; e.g. 3FC on COM1 .. 4
- push DS
- mov ax,BIOSDATA
- mov DS,ax
- xor bx,bx
- assume DS:BIOSDATA
- lea si,BIOSComAddrs ; 4 words of device address
- mov cx,4
-
- KillLoop:
- lodsw ; ax = next device address
- cmp ax,bx ; is it zero?
- je NoCom ; yes, then there is nothing to do.
- mov dx,ax ; dx=port base
- add dx,4 ; dx=port of modem control reg
- mov ax,bx ; ax=0
- out dx,al ; clear modem control device reg
- NoCom:
- loop KillLoop ; repeat for 4 com ports
- pop DS
- ret
- KillComs EndP
-
- ;===============================================================
-
- DiskReset Proc Near
-
- ; Ask DOS to flush her buffers.
- ; Presumably, cachers will intercept this and flush their
- ; buffers too.
-
- mov ah,0dh ; disk reset function
- int 021h ; call DOS
- ret
- DiskReset EndP
-
- ;===============================================================
-
- Breath Proc Near
-
- ; Waste 20 ticks to give the world time to settle down
- ; A delayed write cache has time to flush etc.
-
- Call GetTicks ; time in cx:dx
- add dx,020d
- adc cx,0
- mov word ptr QuitTime+0,dx ; Ptr needed because QuitTime is DWORD
- mov word ptr QuitTime+2,cx
- Pause:
- Call GetTicks
- cmp cx,word ptr QuitTime+2 ; quitting time yet?
- ja PauseDone
- cmp DX,word ptr QuitTime+0
- jb Pause
- PauseDone:
- ret
- Breath EndP
-
- ;===============================================================
-
- GetTicks PROC Near
- ; Get time of day in 1/18.2 second clock ticks since midnight.
- ; leaves tick count in cx:dx
-
- mov ah,0
- int 1Ah ; BIOS ticks since midnight
- ; cx:DX is count
- ret
- GetTicks EndP
-
- ;==============================================================
-
- BootDESQ Proc Near
-
- ; reboot Desqview if present
-
- @CALL DVPRESENT
- test ax,ax
- jnz DESQPresent
- DESQAbsent:
- ret
-
- DESQPresent:
- call Alone
- test ax,ax
- jz ManualClose
- ret ; We are alone, we can safely auto-reboot
-
- ManualClose: ; must ask user to manually close windows
- ; or manually reboot.
- lea dx,DESQMsg
- call Say
-
- NowIsTheEnd:
- ; ; loop till he reboots
- @Call PAUSE ; give up rest of slice
- ; we CANNOT call Alone and autoreboot when
- ; all windows closed, because Alone twitches
- ; the windows making it impossible to close them.
- jmp NowIsTheEnd
-
- BootDESQ Endp
-
- ;==============================================================
-
- Alone Proc Near
-
- Comment √
-
- Returns AX=0 if we are not alone, AX=1 if alone.
-
- Determine if 1, or more than 1 window is currently open under
- DESQview. Note that we assume that we are running under DV and
- do not test for it.
-
- Program works by asking DV to notify when window goes to
- background, then asks to be put in the background. If there are
- no other windows open, there is no background, hence no message.
- I am unable to think of an easy way to count the number of
- windows.
-
- Unfortunately, a side effect of this method is the windows
- rapidly swap on the screen making the screen unreadable as Alone
- executes.
-
- Code based on the ONEWIN program by Phil Graham [BIXname
- pgraham] of Dynamic Data. He restricts this code to
- non-commerical use.
-
-
- End Comment √
-
- Data Segment
-
- make_bottom db 1Bh,10h,2,0,04Bh,0C9h
- ; makes receiving application bottommost and notify when background
- make_bottom_length equ $-make_bottom
-
- make_fore db 1Bh,10h,1,0,0C1h ; makes receiving application for
- make_fore_length equ $-make_fore
-
- Data EndS
-
- @send open,mailme ; open my mailbox for notification
- @send erase,mailme ; clear out any old messages
- lea di,make_bottom ; address of make-bottom stream
- @push DSDI ; push address as 1st parm
- mov cx,make_bottom_length ; length of stream
- xor dx,dx ; convert to dword
- @push DXCX
- @send write,me ; move me to bottom of window list
- @call pause ; be sure notify message gets send
- @send sizeof,mailme ; any messages in my mailbox?
- @pop ESSI ; # of messages in SI
- lea di,make_fore ; address of make-foreground stream
- @push DSDI ; push address as 1st parm
- mov cx,make_fore_length ; length of stream
- xor dx,dx ; convert to dword
- @push DXCX
- @send write,me ; move me to bottom of window list
- test si,si ; did I get move-to-bottom message
- jz OnlyOne ; NO! I must be the only window open
- mov ax,0 ; There are other windows active
- ret
-
- OnlyOne:
- mov ax,1 ; we are alone, -- the only window
- ret
-
- Alone EndP
-
- ;==============================================================
-
- BootWIN3E Proc Near
- ; reboot WIN3E if present
-
- mov ax,1600h ; Test for Windows 3E 4E.
- int 2fh
- and ax,07fh ; AL = 00 if nothing, WIN3r, or WIN3s
- ; 01 if WIN 2.x
- ; 03 if WIN3e
- ; 04 if WIN4e
- ; 7F if WIN 2.x
- ; else treat as nothing
- cmp al,3
- je WIN3EPresent
- cmp al,4
- je WIN3EPresent
-
- WIN3EAbsent:
- ret
-
- WIN3EPresent:
- lea dx,WIN3EMsg
- call Say
-
- WaitForTheEnd:
- ; loop endlessly till he reboots
- mov ah,0bH ; check if char waiting
- int 21h ; this should give Windows a hint we are idling
- jmp WaitForTheEnd
-
- BootWIN3E Endp
-
- ;==============================================================
-
- Boot Proc Near
-
- ; set system reset flag at 0040:0072 to 01234 for warm or 0 for cold
- mov ax,BIOSDATA
- mov ds,ax
- assume ds:BIOSDATA
- mov ax,MyWarmFlag
- mov BIOSWarmFlag,ax
- ; far jump to FFFF:0000 alias F000:FFF0
- jmp BIOSReset ; to simulate a Ctrl-Alt-Del
- assume ds:code
-
- Boot Endp
-
- ;==============================================================
-
- Abort:
- ; error exit
- mov ax, 4c04h ; ERRORLEVEL = 4
- int 21h ; DIE
- ; we do not reboot.
-
- ;==============================================================
-
- Start endp
-
- ;==========================
- CODE ends ; end of code segment
- end Start
-