home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Serving the Web
/
ServingTheWeb1995.disc1of1.iso
/
connect
/
tcpip
/
crynwr
/
pktd11b
/
winpkt.asm
< prev
next >
Wrap
Assembly Source File
|
1993-11-17
|
17KB
|
623 lines
version equ 2
; File WINPKT.ASM 8 Dec 1991
; Provides a Packet Driver interface between Windows 3 Enhanced mode
; applications and a real Packet Driver. This attempts to solve the problem
; of Windows moving applications around in memory willy nilly. Install WINPKT
; after the Packet Driver and before starting Windows.
; Command line is:
; WINPKT WINPKT_interrupt number PD_interrupt_number
; with both in the range of 60h to 7fh.
; Build with the Clarkson Packet Driver Collection subprograms:
; masm WINPKT;
; link WINPKT;
; exe2bin WINPKT.EXE WINPKT.COM
; del WINPKT.EXE
;
include defs.asm
; Copyright, 1988-1992, Russell Nelson
; Copyright, 1991, Roger F. James
; Code revised slightly, formatting cleaned up enormously, added
; documentation, Joe R. Doupnik, jrd@cc.usu.edu, Utah State Univ,
; 8 Dec 1991.
; This program is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, version 1.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program; if not, write to the Free Software
; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
code segment word public
assume cs:code, ds:code, es:nothing
org 2ch
phd_environ dw 0
org 80h
phd_dioa label byte
org 100h
start: jmp start_1
even
;Debugging stuff
;total_pkts dw 0
;gvm_pkts dw 0
;bvm_pkts dw 0
per_handle struc
in_use db 0 ; non-zero if this handle is in use
their_handle dw 0 ; lower layer handle
recv_handler dd 0 ; receiver upcall
vm_id dw 0 ; VM_ID for this handler
per_handle ends
handles per_handle MAX_HANDLE dup(<>)
end_handles label byte
is_186 db 0 ;=0 if 808[68], =1 if 80[123]86.
is_286 db 0 ;=0 if 80[1]8[68], =1 if 80[234]86.
is_386 db 0 ;=0 if 80[12]8[68], =1 if 80[34]86.
regs struc ; stack offsets of incoming regs
_ES dw ?
_DS dw ?
_BP dw ?
_DI dw ?
_SI dw ?
_DX dw ?
_CX dw ?
_BX dw ?
_AX dw ?
_IP dw ?
_CS dw ?
_F dw ? ; flags, Carry flag is bit 0
regs ends
CY equ 0001h
EI equ 0200h
bytes struc ; stack offsets of incoming regs
dw ? ; es, ds, bp, di, si are 16 bits
dw ?
dw ?
dw ?
dw ?
_DL db ?
_DH db ?
_CL db ?
_CH db ?
_BL db ?
_BH db ?
_AL db ?
_AH db ?
bytes ends
old_isr dd 0 ; old pkt driver int
their_2f_isr dd 0 ; original int 2f ISR
; The following are globals that assume that the code that access them
; single threads.
MAX_BUFFER_LEN equ 1520
our_buffer db MAX_BUFFER_LEN dup (0)
buffer_flag db 0
buffer_len dw 0
their_handler dd 0 ; receiver handler to call
their_bx dw 0
;
;
vmm_running db 0 ; 386 virtual machine manager is running
our_handle dw 0 ; current top level handle
include movemem.asm
our_isr:
jmp our_isr_0 ; the required signature.
db 'PKT DRVR',0
db 'WINPKT',0
our_isr_0: ; check if it one of the calls we
assume ds:nothing ; want to intercept (passes addresses)
cmp ah,2 ; f_access_type?
je our_isr_2 ; e = yes
cmp ah,3 ; f_release_type?
je our_isr_2
cmp ah,5 ; f_terminate
je our_isr_2
cmp ah,8 ; f_stop
je our_isr_2
our_isr_1: ; nothing needing intercepion
jmp old_isr ; chain to the original Packet Driver
our_isr_2:
push ax ; We are interested in this one
push bx ; so save some registers
push cx
push dx
push si
push di
push bp
push ds
push es
cld
mov bx,cs ; set up DS
mov ds,bx
assume ds:code
mov bp,sp ; use bp to access the original regs
and _F[bp],not CY ; start by clearing the carry flag
cmp ah,2 ; f_access_type?
jne our_isr_3 ; ne = no (it's special here)
jmp f_access_type
our_isr_3:
cmp ah,3 ; f_release_type?
jne our_isr_4 ; ne = no
jmp f_release_type
our_isr_4:
cmp ah,5 ; f_terminate?
jne our_isr_5 ; ne = no
jmp f_terminate
our_isr_5:
jmp f_stop ; must be f_stop
our_isr_error:
mov _DH[bp],dh ; error code
or _F[bp],CY ; return their carry flag
our_isr_return:
pop es
pop ds
pop bp
pop di
pop si
pop dx
pop cx
pop bx
pop ax
iret
; Windows (and many many other programs) use the Int 2Fh Multiplexor link,
; and each is supposed to grab it's own calls as seen in AX, or chain them
; to the previous Int 2Fh owner. Windows 3 uses function 16h for most work.
; This is our Int 2Fh routine.
our_2f_isr:
assume ds:nothing, es:nothing
cmp ax,1608h ; Windows Enhanced "Init completed" broadcast?
jne our_2f_1 ; ne = not that function, chain it
mov vmm_running,1 ; remember that Windows has started
jmp their_2f_isr ; pass it on down the chain
our_2f_1:
cmp ax,1609h ; Windows Enhanced "Begin Exit" broadcast?
jne our_2f_2 ; ne = no
mov vmm_running,0 ; remember that Windows has stopped
our_2f_2:
jmp their_2f_isr ; propagate broadcasts down the Int 2Fh chain
our_handler: ; Receive upcalls from the Packet Driver
or ax,ax ; first (AX=0) call to get buffer?
jnz our_handler_2 ; nz = no, must be second upcall
cmp buffer_flag,1 ; must buffer, is it free?
je our_handler_1 ; e = no, busy
cmp cx,MAX_BUFFER_LEN ; pkt larger than our buffer?
ja our_handler_1 ; a = yes, too large
mov buffer_flag,1 ; mark buffer as busy now
mov buffer_len,cx ; store pkt length
mov ax,cs
mov es,ax ; segment of our buffer
mov di,offset our_buffer ; tell PD es:di is the buffer address
retf
our_handler_1:
xor ax,ax ; reject the packet by returning es:di = NULL
mov es,ax
xor di,di
retf
our_handler_2: ; second upcall, packet transfer complete
mov their_bx,bx ; save their registers
mov dx,bx
mov bx,cs ; set our data segment
mov ds,bx
assume ds:code
mov bx,offset handles ; array of PD handles
our_handler_3:
cmp [bx].their_handle,dx ; dx is upcoming handle
je our_handler_4 ; found their handle
add bx,(size per_handle) ; next handle
cmp bx,offset end_handles ; examined all handles?
jb our_handler_3 ; b = no, continue.
; get here if no matching handle
mov buffer_flag,0 ; mark the buffer free
retf
our_handler_4: ; found the handle
; inc total_pkts
mov ax,[bx].recv_handler.segm ; appliation's call address
mov their_handler.segm,ax
mov ax,[bx].recv_handler.offs
mov their_handler.offs,ax
push bx
mov ax,1683h ; Windows, get current vir mach ident
int 2fh
mov ax,bx ; ident returned in bx
pop bx
cmp ax,[bx].vm_id ; same as the one the app is using?
je our_handler_5 ; e = yes, correct VM is running
jmp our_handler_7 ; no, another VM is running, switch to wanted
our_handler_5:
; inc gvm_pkts
call pass_to_app ; copy buffer to application, via double call
retf
pass_to_app:
xor ax,ax ; set up register for first upcall to app
mov bx,their_bx ; handle from Packet Driver
mov cx,buffer_len ; packet size
push ds
call their_handler ; do first upcall (request buffer address)
pop ds
mov ax,es ; check for 0:0 as reject value
or ax,ax
jnz pass_to_app_1 ; nz = have an address
or di,di ; check for 0:offset (rather unlikely)
jnz pass_to_app_1 ; nz = have an offset
mov buffer_flag,0 ; packet is being declined, free our buffer
ret
pass_to_app_1: ; copy from our buffer to app's es:di
push di
mov cx,buffer_len
mov si,offset our_buffer
cld
call movemem ; copy frame into apps buffer
mov ax,1 ; set up regs for second upcall
mov bx,their_bx ; handle
mov cx,buffer_len ; report packet length too
pop si
mov dx,es
push ds
mov ds,dx
assume ds:nothing
call their_handler ; call the application
pop ds
assume ds:code
mov buffer_flag,0 ; free buffer
ret
; Windows Enhanced, request virtual machine in bx, and call back at es:di
; when it's ready (which, knowing Windows, may take quite a while, hence
; the requirement to buffer the packet to clear the lan board and ints).
our_handler_7:
; inc bvm_pkts
mov ax,1685h ; request switch VMs and callback
mov bx,[bx].vm_id ; virtual machine of the app
xor cx,cx ; flags (bits 0 and 1), zero is don't wait
mov dx,40h ; dx:si is priority boost
xor si,si
movseg es,cs
mov di,offset our_callback
int 2fh
retf
assume ds:nothing
our_callback: ; get here with correct virtual machine
push ax ; call application twice (a la PD) to deliver
push bx ; the buffered packet
push cx
push dx
push si
push di
push ds
push es
push bp
mov ax,cs
mov ds,ax ; set up our ds
assume ds:code
call pass_to_app
pop bp
pop es
pop ds
assume ds:nothing
pop di
pop si
pop dx
pop cx
pop bx
pop ax
iret
assume ds:code
f_access_type: ; register for a packet Type
mov bx,offset handles ; array of PD handles
access_type_1:
cmp [bx].in_use,0 ; is this handle in use?
je access_type_2 ; e = yes, found a free one
add bx,(size per_handle) ; next handle
cmp bx,offset end_handles ; examined all handles?
jb access_type_1 ; b = no, continue
jmp access_type_space ; no handle found, return error
access_type_2:
mov our_handle,bx ; save our handle
mov [bx].in_use,1 ; make handle as in-use
cmp vmm_running,0 ; is Windows Enhanced mode running?
je access_type_3 ; e = no, don't bother to redirect
mov [bx].recv_handler.segm,es
mov [bx].recv_handler.offs,di
mov bx,cs
mov es,bx
mov di,offset our_handler
access_type_3:
push ds
mov bx,_DS[bp]
mov ds,bx
assume ds:nothing
mov bx,_BX[bp] ; restore callers registers
pushf
call old_isr ; call Packet Driver
pop ds
assume ds:code
mov bx,our_handle
jnc access_type_4 ; nc = success
mov [bx].in_use,0 ; failed, free our handle
jmp our_isr_error
access_type_4:
mov [bx].their_handle,ax ; handle returned in ax
mov _AX[bp],ax ; save return handle
cmp vmm_running,0 ; Windows Enhanced mode running?
je access_type_5 ; e = no
push bx ; Windows "Get Current Virtual Mach"
mov ax,1683h
int 2fh ; get current VM_ID to bx
mov ax,bx
pop bx
mov [bx].vm_id,ax ; save ident as part of our handle
access_type_5:
jmp our_isr_return
access_type_space:
mov dh,NO_SPACE
jmp our_isr_error
f_release_type:
mov bx,_BX[bp] ; restore callers registers
pushf
call old_isr
jnc release_type_1 ; nc = success
jmp our_isr_error
release_type_1:
mov ax,_BX[bp] ;just in case
mov bx,offset handles
release_type_2:
cmp [bx].their_handle,ax ; compare handles
je release_type_3 ; e = found a match
add bx,(size per_handle) ; next handle
cmp bx,offset end_handles ; examined all handles?
jb release_type_2 ; b = no, continue
jmp err_bad_handle ; no handle found, return error
release_type_3:
mov [bx].in_use,0 ; say handle is no longer in use
jmp our_isr_return
err_bad_handle:
mov dh,BAD_HANDLE ; dh is error code
jmp our_isr_error
f_terminate:
mov bx,_BX[bp] ; restore callers registers
pushf
call old_isr
jnc terminate_1 ; nc = success
jmp our_isr_error
terminate_1:
mov ax,_BX[bp] ; just in case
mov bx,offset handles
terminate_2:
cmp [bx].their_handle,ax ; compare handles
je terminate_3 ; e = found a match
add bx,(size per_handle) ; next handle
cmp bx,offset end_handles ; examined all handles?
jb terminate_2 ; b = no, continue
jmp err_bad_handle ; no match, return error
terminate_3:
mov [bx].in_use,0 ; mark handle as free
mov bx,offset handles ; check that all handles are free
terminate_4:
cmp [bx].in_use,0 ; is this handle free?
jne terminate_5 ; ne = no, so can't exit completely
add bx,(size per_handle) ; next handle
cmp bx,offset end_handles ; examined all handles?
jb terminate_4 ; b = no, continue examination
mov ah,35h ; got owner of Int 2Fh
mov al,2fh
int 21h ; to see if it's still us
mov ax,es
mov cx,cs
cmp ax,cx ; our segment?
jne terminate_5 ; ne = no, can't terminate
cmp bx,offset our_2f_isr ; our offset?
jne terminate_5 ; ne = no, can't terminate
mov al,2fh ; restore Int 2f
mov ah,25h
push ds
lds dx,their_2f_isr ; previous owner now is current owner
int 21h
pop ds
movseg es,cs
mov ah,49h ; free our memory
int 21h
jmp our_isr_return
terminate_5:
mov dh,CANT_TERMINATE ; error code
jmp our_isr_error
; Stop the packet driver doing upcalls. Also a following terminate will
; always succed (no in use handles any longer).
f_stop:
mov bx,_BX[bp] ; restore caller's registers
pushf
call old_isr
mov bx,offset handles
f_stop_2:
mov [bx].in_use,0 ; say handle is free
add bx,(size per_handle) ; next handle
cmp bx,offset end_handles ; done all?
jb f_stop_2 ; b = not yet
clc
ret
end_resident label byte
include printnum.asm
include decout.asm
include digout.asm
include chrout.asm
usage_msg label byte
db ' Usage: WINPKT <packet_int_number>',CR,LF
db ' Install WINPKT after the regular Packet Driver, but'
db CR,LF,' before starting Windows 3.$'
copyright_msg label byte
db "Virtual packet driver for Windows 3.x, version ",'0'+(majver / 10),'0'+(majver mod 10),".",'0'+version,CR,LF
db "Portions Copyright 1991 Roger F. James",CR,LF,'$'
copyleft_msg label byte
db "Packet driver skeleton copyright 1988-90, Russell Nelson.",CR,LF
db "This program is free software; see the file COPYING for details."
db CR,LF
db "NO WARRANTY; see the file COPYING for details.",CR,LF
db CR,LF
crlf_msg db CR,LF,'$'
entry_point db 0,0,0,0
not_found_msg db CR,LF,'There is no packet driver at $'
new_int_msg db CR,LF,'Virtual packet driver installed on interrupt $'
not_found_error:
mov dx,offset not_found_msg
mov di,offset entry_point
call print_number
mov ax,4c05h ; exit to DOS with errorlevel = 5
int 21h
usage_error:
mov dx,offset usage_msg
error: mov ah,9
int 21h
mov ax,4c0ah ; give errorlevel 10
int 21h
start_1:cld
mov dx,offset copyright_msg
mov ah,9
int 21h
mov dx,offset copyleft_msg
mov ah,9
int 21h
mov si,offset phd_dioa+1
call skip_blanks ; end of line?
cmp al,CR
je usage_error ; e = yes
chk_options:
call skip_blanks
cmp al,'-' ; any options?
jne no_more_opt
usage_error_j_1:
jmp usage_error
no_more_opt:
mov di,offset entry_point
call get_number
call skip_blanks
cmp al,CR
jne usage_error
mov al,entry_point
call verify_packet_int
jnc packet_int_ok ; nc = success
jmp error
packet_int_ok:
jne not_found_error ; error if no Packet Driver
;Determine the processor type. The 8088 and 8086 will actually shift ax
;over by 33 bits, while the 80[123]86 use a shift count mod 32.
mov cl,33
mov ax,0ffffh
shl ax,cl ;186 or better?
jz processor_identified ;no.
mov is_186,1
push sp
pop ax
cmp ax,sp ;286 or better?
jne processor_identified ;no.
mov is_286,1
pushf
pop ax
or ax,7000h ;the 386 lets us set these bits
push ax
popf ;this should be a real popf.
pushf
pop ax
test ax,7000h ;did the bits get set?
je processor_identified
mov is_386,1
processor_identified:
mov ah,35h ; get Packet Driver interrupt routine
mov al,entry_point
int 21h
mov old_isr.offs,bx ; save here
mov old_isr.segm,es
mov ah,25h ; install our packet interrupt
mov dx,offset our_isr
int 21h
mov ah,35h ; get Int 2Fh interrupt routine
mov al,2fh
int 21h
mov their_2f_isr.offs,bx ; save here
mov their_2f_isr.segm,es
mov ah,25h ;install our 2f interrupt
mov dx,offset our_2f_isr
int 21h
mov ah,49h ; free our environment, because
mov es,phd_environ ; we won't need it
int 21h
mov bx,1 ; get the stdout handle
mov ah,3eh ; close it in case they redirected it
int 21h
mov dx,offset end_resident
add dx,0fh ; round up to next highest paragraph
mov cl,4
shr dx,cl
mov ah,31h ; terminate, stay resident
xor al,al
int 21h
include verifypi.asm
include getnum.asm
include getdig.asm
include skipblk.asm
include printea.asm
include crlf.asm
code ends
end start