525 lines
16 KiB
NASM
525 lines
16 KiB
NASM
PAGE 58,132
|
|
;******************************************************************************
|
|
TITLE SAGE - SAGE VxD
|
|
;******************************************************************************
|
|
;
|
|
; Title: SAGE.ASM - SAGE VxD
|
|
;
|
|
; Version: 0.060
|
|
;
|
|
; Date: 04/18/95
|
|
;
|
|
; Author: Bob Eichenlaub
|
|
;
|
|
;------------------------------------------------------------------------------
|
|
;
|
|
; Change log:
|
|
;
|
|
; DATE REV DESCRIPTION
|
|
; ----------- --- -----------------------------------------------------------
|
|
; 04/18/95 Initial version - be
|
|
; 07/06/95 serial IRQ detection - be; credit to rjc for the basic approach
|
|
; 05/23/97 [darrenmi] major clean-up and support multiple clients
|
|
; for IE4
|
|
;
|
|
;==============================================================================
|
|
|
|
.386p
|
|
|
|
;******************************************************************************
|
|
; I N C L U D E S
|
|
;******************************************************************************
|
|
|
|
.XLIST
|
|
INCLUDE VMM.Inc
|
|
INCLUDE VWIN32.Inc
|
|
INCLUDE VPICD.Inc
|
|
WIN41SERVICES equ 1 ; need _SHELL_Update_User_Activity_Ex service
|
|
INCLUDE SHELL.Inc
|
|
INCLUDE VXDLDR.Inc
|
|
INCLUDE regdef.Inc
|
|
INCLUDE Debug.Inc
|
|
INCLUDE Sage.Inc
|
|
.LIST
|
|
|
|
;public SAGE_Update_User_Activity
|
|
|
|
;******************************************************************************
|
|
; V I R T U A L D E V I C E D E C L A R A T I O N
|
|
;------------------------------------------------------------------------------
|
|
; The VxD declaration statement defines the VxD name, version number,
|
|
; control proc entry point, VxD ID, initialization order, and VM API
|
|
; entry points.
|
|
;
|
|
; - Defined VxD ID: See VXDID.TXT for more information
|
|
; - Init order: If serial port detection is enabled then this Vxd MUST loaded
|
|
; before VCOMM.VxD and after VPICD.VxD,
|
|
; See VMM.INC for the complete
|
|
; definition of the init order of the standard devices.
|
|
;
|
|
;******************************************************************************
|
|
|
|
Declare_Virtual_Device sage, 1, 0, SAGE_Control, VSageID, UNDEFINED_INIT_ORDER
|
|
|
|
;******************************************************************************
|
|
; D A T A
|
|
;******************************************************************************
|
|
|
|
;
|
|
; Locked data
|
|
;
|
|
VxD_LOCKED_DATA_SEG
|
|
|
|
Window_List dd 0, 0, 0, 0, 0, 0, 0, 0
|
|
cClients dd 0 ; number of valid windows in window list
|
|
Time_Out_Idle dd 10000 ; the interval between message posts
|
|
Time_Out_Handle dd 0 ; Handle to the global time out we create
|
|
PtrSHELL_SUUAE_INFO dd 0 ; pointer to the SHELL_SUUAE_INFO structure
|
|
PrevActiveDisplay dd 0 ; last screen or user input activity
|
|
PrevActiveSystem dd 0 ; last system activity
|
|
Hooked_Proc dd 0 ; shell's user_activity entry that we hooked
|
|
|
|
; Fake user activity info structure in case on Win95.
|
|
FakeSUUAE_INFO _SHELL_SUUAE_INFO <0,0,0,0,0>
|
|
|
|
VxD_LOCKED_DATA_ENDS
|
|
|
|
;******************************************************************************
|
|
; C O D E
|
|
;------------------------------------------------------------------------------
|
|
; The 'body' of the VxD is in the standard code segment.
|
|
;******************************************************************************
|
|
|
|
VxD_CODE_SEG
|
|
|
|
BeginProc SAGE_Start_Idle_Timer
|
|
|
|
push esi
|
|
|
|
; check to see if we've already got a timer
|
|
mov esi, [Time_Out_Handle]
|
|
test esi, esi
|
|
jnz start1
|
|
|
|
; get a timer
|
|
mov eax, [Time_Out_Idle]
|
|
mov esi, OFFSET32 SAGE_User_Idle_Check
|
|
VMMCall Set_Global_Time_Out
|
|
mov [Time_Out_Handle], esi
|
|
|
|
start1:
|
|
pop esi
|
|
ret
|
|
|
|
EndProc SAGE_Start_Idle_Timer
|
|
|
|
BeginProc SAGE_Stop_Idle_Timer
|
|
|
|
push esi
|
|
|
|
; check to see if we have a timer
|
|
mov esi, [Time_Out_Handle]
|
|
test esi, esi
|
|
jz stop1
|
|
|
|
; kill it
|
|
VMMCall Cancel_Time_Out
|
|
xor esi, esi
|
|
mov [Time_Out_Handle], esi
|
|
|
|
stop1:
|
|
pop esi
|
|
ret
|
|
|
|
EndProc SAGE_Stop_Idle_Timer
|
|
|
|
|
|
;******************************************************************************
|
|
;
|
|
; SAGE_Device_IO
|
|
;
|
|
; DESCRIPTION:
|
|
; This is the routine that is called when the CreateFile or
|
|
; DeviceIoControl is made
|
|
;
|
|
; ENTRY:
|
|
; ESI = Pointer to args (see VWIN32.INC for struct definition)
|
|
;
|
|
; EXIT:
|
|
; EAX = return value
|
|
;
|
|
; USES:
|
|
; flags
|
|
;
|
|
;==============================================================================
|
|
|
|
BeginProc SAGE_Device_IO
|
|
|
|
mov ecx, [esi.dwIOControlCode]
|
|
test ecx, ecx
|
|
jnz next1
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;
|
|
; DIOC_GETVERSION
|
|
;
|
|
|
|
; obtain a pointer to the shell vxd's activity timer info
|
|
cmp [PtrSHELL_SUUAE_INFO], 0
|
|
jne short getver1
|
|
VxDCall SHELL_Get_Version
|
|
cmp eax, 040Ah
|
|
jae short haveSUUAEX
|
|
|
|
; Running on Win95 so we don't have SHELL_Update_User_Activty_Ex service,
|
|
; hook the shell vxd's activity service to watch activity.
|
|
mov esi, offset32 SAGE_Update_User_Activity
|
|
GetVxDServiceOrdinal eax, SHELL_Update_User_Activity
|
|
VMMCall Hook_Device_Service
|
|
mov eax, offset32 FakeSUUAE_INFO
|
|
jmp short setSUUAE_INFO
|
|
|
|
haveSUUAEX:
|
|
VxDCall _SHELL_Update_User_Activity_Ex, <SUUAE_CONTINUOUS OR SUUAE_CONTINUOUS_CHECK>
|
|
setSUUAE_INFO:
|
|
mov [PtrSHELL_SUUAE_INFO], eax ; (eax) = ptr to SHELL_SUAAE_INFO structure
|
|
|
|
getver1:
|
|
xor eax, eax ; success
|
|
ret
|
|
|
|
next1:
|
|
cmp ecx,-1
|
|
jne next2
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;
|
|
; DIOC_CLOSE
|
|
;
|
|
|
|
; see if we have clients to close
|
|
cmp [cClients], 0
|
|
jz close1
|
|
|
|
; we do... see if it's the last one...
|
|
dec [cClients]
|
|
cmp [cClients], 0
|
|
jnz close1
|
|
|
|
; last client going away - clean up
|
|
call SAGE_Stop_Idle_Timer
|
|
|
|
cmp [PtrSHELL_SUUAE_INFO], offset32 FakeSUUAE_INFO
|
|
jne short close1
|
|
|
|
; unhook activity service
|
|
GetVxDServiceOrdinal eax,SHELL_Update_User_Activity
|
|
mov esi, offset32 SAGE_Update_User_Activity
|
|
VMMCall Unhook_Device_Service
|
|
xor eax, eax
|
|
mov [PtrSHELL_SUUAE_INFO], eax ; clear pointer
|
|
|
|
close1:
|
|
xor eax,eax ; success
|
|
ret
|
|
|
|
next2:
|
|
cmp ecx,1
|
|
jne next3
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;
|
|
; Set handle and timeout
|
|
;
|
|
mov ebx, [esi.lpvInBuffer]
|
|
|
|
; Try to find window handle
|
|
mov eax, [ebx]
|
|
mov ecx, [cClients]
|
|
test ecx, ecx
|
|
jz addtolist
|
|
|
|
ioloop:
|
|
cmp eax, [Window_List + 4 * ecx - 4]
|
|
je timeout
|
|
|
|
dec ecx
|
|
jnz ioloop
|
|
|
|
; Can't find it - add it to window list
|
|
mov ecx, [cClients]
|
|
cmp ecx, 8
|
|
jnl timeout
|
|
|
|
addtolist:
|
|
inc [cClients]
|
|
mov [Window_List + 4 * ecx], eax
|
|
|
|
timeout:
|
|
; update timeout if specified
|
|
mov eax, [ebx+8]
|
|
test eax, eax
|
|
jz config1
|
|
|
|
mov [Time_Out_Idle], eax
|
|
|
|
config1:
|
|
call SAGE_Start_Idle_Timer
|
|
|
|
xor eax, eax ; success
|
|
ret
|
|
next3:
|
|
cmp ecx, 2
|
|
jne next4
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;
|
|
; Query last activity
|
|
;
|
|
mov ebx, [esi.lpvInBuffer]
|
|
mov edx, [PtrSHELL_SUUAE_INFO]
|
|
.errnz ssiHoldSystem-ssiHoldDisplay-1
|
|
cmp word ptr [edx].ssiHoldDisplay, 0
|
|
jne short lact1 ; system or display in "hold" state
|
|
mov eax, [edx].ssiTimeLastActiveDisplay
|
|
cmp eax, [edx].ssiTimeLastActiveSystem
|
|
jae short lact2
|
|
mov eax, [edx].ssiTimeLastActiveSystem
|
|
jmp short lact2
|
|
|
|
lact1: VMMCall Get_Last_Updated_System_Time
|
|
lact2: mov [ebx], eax
|
|
xor eax, eax
|
|
ret
|
|
|
|
next4:
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;
|
|
; some unsupported value...
|
|
;
|
|
mov eax, ERROR_NOT_SUPPORTED
|
|
ret
|
|
|
|
EndProc SAGE_Device_IO
|
|
|
|
|
|
VxD_CODE_ENDS
|
|
|
|
|
|
|
|
;******************************************************************************
|
|
; P A G E L O C K E D C O D E
|
|
;------------------------------------------------------------------------------
|
|
; Memory is a scarce resource. Use this only where necessary.
|
|
;******************************************************************************
|
|
VxD_LOCKED_CODE_SEG
|
|
|
|
;******************************************************************************
|
|
;
|
|
; SAGE_Control
|
|
;
|
|
; DESCRIPTION:
|
|
;
|
|
; This is a call-back routine to handle the messages that are sent
|
|
; to VxD's to control system operation. Every VxD needs this function
|
|
; regardless if messages are processed or not. The control proc must
|
|
; be in the LOCKED code segment.
|
|
;
|
|
; The Control_Dispatch macro used in this procedure simplifies
|
|
; the handling of messages. To handle a particular message, add
|
|
; a Control_Dispatch statement with the message name, followed
|
|
; by the procedure that should handle the message.
|
|
;
|
|
; ENTRY:
|
|
; EAX = Message number
|
|
; EBX = VM Handle
|
|
;
|
|
;==============================================================================
|
|
|
|
BeginProc SAGE_Control
|
|
|
|
Control_Dispatch W32_DEVICEIOCONTROL, SAGE_Device_IO
|
|
clc
|
|
ret
|
|
|
|
EndProc SAGE_Control
|
|
|
|
|
|
BeginDoc
|
|
;******************************************************************************
|
|
;
|
|
; SAGE_Update_User_Activity
|
|
;
|
|
; DESCRIPTION:
|
|
;
|
|
; This service is called by VMD, VKD to tell us that user input occured
|
|
; ENTRY: None
|
|
; EXIT: None
|
|
; USES: NONE
|
|
;==============================================================================
|
|
EndDoc
|
|
BeginProc SAGE_Update_User_Activity, HOOK_PROC, Hooked_Proc
|
|
|
|
push eax
|
|
|
|
; save off the time
|
|
VMMCall Get_Last_Updated_System_Time
|
|
mov [FakeSUUAE_INFO.ssiTimeLastActiveDisplay], eax
|
|
|
|
pop eax
|
|
jmp Hooked_Proc
|
|
|
|
EndProc SAGE_Update_User_Activity
|
|
|
|
|
|
VxD_LOCKED_CODE_ENDS
|
|
|
|
VxD_PAGEABLE_CODE_SEG
|
|
|
|
;******************************************************************************
|
|
;
|
|
; SAGE_User_Idle_Check
|
|
;
|
|
; DESCRIPTION:
|
|
;
|
|
; This checks if key/mouse or serial port (comm) event has occurred.
|
|
;
|
|
; Entry:
|
|
; None
|
|
; Exit:
|
|
; None
|
|
; Uses:
|
|
; ALL
|
|
;******************************************************************************
|
|
|
|
BeginProc SAGE_User_Idle_Check,High_Freq,PUBLIC
|
|
|
|
;
|
|
; clear handle
|
|
;
|
|
xor ecx, ecx
|
|
mov [Time_Out_Handle], ecx
|
|
|
|
;
|
|
; check for idleness
|
|
;
|
|
mov eax, [PtrSHELL_SUUAE_INFO] ; (eax) = ptr to SHELL_SUAAE_INFO structure
|
|
.errnz ssiHoldSystem-ssiHoldDisplay-1
|
|
cmp word ptr [eax].ssiHoldDisplay, 0
|
|
jne short holdActive ; system or display in "hold" state
|
|
mov ecx, [eax].ssiTimeLastActiveDisplay
|
|
mov edx, [eax].ssiTimeLastActiveSystem
|
|
cmp ecx, [PrevActiveDisplay]
|
|
jne notIdle ; display activity changed
|
|
cmp edx, [PrevActiveSystem]
|
|
je ResetTimer ; no display or system activity since last time
|
|
|
|
;
|
|
; Not idle so post a message to all clients who want to know
|
|
;
|
|
notIdle:
|
|
mov [PrevActiveDisplay], ecx ; update idle times for next time
|
|
mov [PrevActiveSystem], edx
|
|
holdActive:
|
|
|
|
xor eax, eax
|
|
mov ecx, [cClients]
|
|
test ecx, ecx
|
|
jz ResetTimer
|
|
|
|
loop0:
|
|
|
|
; get next window
|
|
mov ebx, [4 * ecx + Window_List - 4]
|
|
|
|
; skip if it's -1
|
|
cmp ebx, -1
|
|
je loop1
|
|
|
|
; post message
|
|
push ecx
|
|
VxDCall _SHELL_PostMessage, <ebx, WM_SAGE_MSG, eax, eax, eax, eax>
|
|
pop ecx
|
|
|
|
loop1:
|
|
dec ecx
|
|
jnz loop0
|
|
|
|
;
|
|
; reset the timer so we check again later
|
|
;
|
|
ResetTimer:
|
|
call SAGE_Start_Idle_Timer
|
|
ret
|
|
|
|
EndProc SAGE_User_Idle_Check
|
|
|
|
VxD_PAGEABLE_CODE_ENDS
|
|
|
|
|
|
;******************************************************************************
|
|
; R E A L M O D E C O D E
|
|
;******************************************************************************
|
|
|
|
;******************************************************************************
|
|
;
|
|
; Real mode initialization code
|
|
;
|
|
; DESCRIPTION:
|
|
; This code is called when the system is still in real mode, and
|
|
; the VxDs are being loaded.
|
|
;
|
|
; This routine as coded shows how a VxD (with a defined VxD ID)
|
|
; could check to see if it was being loaded twice, and abort the
|
|
; second without an error message. Note that this would require
|
|
; that the VxD have an ID other than Undefined_Device_ID. See
|
|
; the file VXDID.TXT more details.
|
|
;
|
|
; ENTRY:
|
|
; AX = VMM Version
|
|
; BX = Flags
|
|
; Bit 0: duplicate device ID already loaded
|
|
; Bit 1: duplicate ID was from the INT 2F device list
|
|
; Bit 2: this device is from the INT 2F device list
|
|
; EDX = Reference data from INT 2F response, or 0
|
|
; SI = Environment segment, passed from MS-DOS
|
|
;
|
|
; EXIT:
|
|
; BX = ptr to list of pages to exclude (0, if none)
|
|
; SI = ptr to list of instance data items (0, if none)
|
|
; EDX = DWORD of reference data to be passed to protect mode init
|
|
;
|
|
;==============================================================================
|
|
|
|
VxD_REAL_INIT_SEG
|
|
|
|
BeginProc SAGE_Real_Init_Proc
|
|
|
|
test bx, Duplicate_Device_ID ; check for already loaded
|
|
jnz short duplicate ; jump if so
|
|
|
|
xor bx, bx ; no exclusion table
|
|
xor si, si ; no instance data table
|
|
xor edx, edx ; no reference data
|
|
|
|
mov ax, Device_Load_Ok
|
|
ret
|
|
|
|
duplicate:
|
|
mov ax, Abort_Device_Load + No_Fail_Message
|
|
ret
|
|
|
|
EndProc SAGE_Real_Init_Proc
|
|
|
|
|
|
VxD_REAL_INIT_ENDS
|
|
|
|
|
|
END
|