diff options
Diffstat (limited to '')
-rw-r--r-- | private/nw/vwipxspx/tsr/asmmacro.inc | 343 | ||||
-rw-r--r-- | private/nw/vwipxspx/tsr/debugmac.inc | 356 | ||||
-rw-r--r-- | private/nw/vwipxspx/tsr/makefile | 159 | ||||
-rw-r--r-- | private/nw/vwipxspx/tsr/segorder.inc | 113 | ||||
-rw-r--r-- | private/nw/vwipxspx/tsr/vwipxspx.asm | 711 |
5 files changed, 1682 insertions, 0 deletions
diff --git a/private/nw/vwipxspx/tsr/asmmacro.inc b/private/nw/vwipxspx/tsr/asmmacro.inc new file mode 100644 index 000000000..0b7b2db16 --- /dev/null +++ b/private/nw/vwipxspx/tsr/asmmacro.inc @@ -0,0 +1,343 @@ +;++ +; +;Copyright (c) 1991 Microsoft Corporation +; +;Module Name: +; +; asmmacro.inc +; +;Abstract: +; +; Contains macros to extend masm functionality: +; +; jmpc +; jmpnc +; jmpne +; jmps +; _mkjmp +; +; +;Author: +; +; Richard L Firth (rfirth) 24-Sep-1991 +; +;Environment: +; +; DOS application mode only +; +;Revision History: +; +; 24-Sep-1991 rfirth +; Created +; +;-- + + + +DEFINED_BIT=020h +;ISDEFINED equ %(.type <thing> and DEFINED_BIT) +LABEL_DEFINED equ <(.type &label and DEFINED_BIT)> + +DEBUG_MACROS = 0 +;DEBUG_MACROS = 1 + + +;*** jmpa +;* +;* jump to label if above. Label can be short (+129, -126 from +;* the first byte of the current jump instruction, if it is a short - ie +;* byte - jump) or near +;* +;* ENTRY label - to jump to +;* +;* EXIT nothing +;* +;* USES nothing +;* +;* ASSUMES 286+ +;* +;*** + +jmpa macro label + _mkjmp ja,jna,&label +endm + +;*** jmpc +;* +;* jump to label if below. Label can be short (+129, -126 from +;* the first byte of the current jump instruction, if it is a short - ie +;* byte - jump) or near +;* +;* ENTRY label - to jump to +;* +;* EXIT nothing +;* +;* USES nothing +;* +;* ASSUMES 286+ +;* +;*** + +jmpb macro label + _mkjmp jb,jnb,&label +endm + +;*** jmpc +;* +;* jump to label if carry flag set. Label can be short (+129, -126 from +;* the first byte of the current jump instruction, if it is a short - ie +;* byte - jump) or near +;* +;* ENTRY label - to jump to +;* +;* EXIT nothing +;* +;* USES nothing +;* +;* ASSUMES 286+ +;* +;*** + +jmpc macro label + _mkjmp jc,jnc,&label +endm + + + +;*** jmpnc +;* +;* jump to label if carry flag NOT set. Label can be short (+129, -126 from +;* the first byte of the current jump instruction, if it is a short - ie +;* byte - jump) or near +;* +;* ENTRY label - to jump to +;* +;* EXIT nothing +;* +;* USES nothing +;* +;* ASSUMES 286+ +;* +;*** + +jmpnc macro label + _mkjmp jnc,jc,&label +endm + + + +;*** jmpne +;* +;* jump to label if zero flag NOT set. Label can be short (+129, -126 from +;* the first byte of the current jump instruction, if it is a short - ie +;* byte - jump) or near +;* +;* ENTRY label - to jump to +;* +;* EXIT nothing +;* +;* USES nothing +;* +;* ASSUMES 286+ +;* +;*** + +jmpne macro label + _mkjmp jne,je,&label +endm + + + +;*** jmpe +;* +;* jump to label if zero flag set. Label can be short (+129, -126 from +;* the first byte of the current jump instruction, if it is a short - ie +;* byte - jump) or near +;* +;* ENTRY label - to jump to +;* +;* EXIT nothing +;* +;* USES nothing +;* +;* ASSUMES 286+ +;* +;*** + +jmpe macro label + _mkjmp je,jne,&label +endm + + + +;*** jmps +;* +;* jump to label. Label can be short (+129, -126 from +;* the first byte of the current jump instruction, if it is a short - ie +;* byte - jump) or near +;* +;* ENTRY label - to jump to +;* +;* EXIT nothing +;* +;* USES nothing +;* +;* ASSUMES 286+ +;* +;*** + +jmps macro label + local l,dist +dist=&label-$ +if1 +if (.type label and DEFINED_BIT) +if ((dist gt 129) or (dist lt -126)) +if DEBUG_MACROS + %out pass1: &label defined and near +endif + jmp &label +else +if DEBUG_MACROS + %out pass1: &label defined and short +endif + jmp short &label +endif +else +if DEBUG_MACROS + %out pass1: &label not defined +endif + org $+3 +endif +else +if ((dist gt 129) or (dist lt -126)) +if DEBUG_MACROS + %out pass2: &label defined and near +endif + jmp &label +else +if DEBUG_MACROS + %out pass2: &label defined and short +endif + jmp short &label + org $+1 +endif +endif +l: +endm + + + +;*** _mkjmp +;* +;* Make a jmp<?> macro. Generate instruction sequence for jump with or +;* without conditional test. Jump may be short (+127/-128 bytes) or near +;* (+32767/-32768 bytes) +;* +;* ENTRY is - short jump instruction +;* in - near jump instruction +;* label - to jump to +;* +;* EXIT nothing +;* +;* USES nothing +;* +;* ASSUMES 286+ +;* +;*** + +_put macro s,v +if2 +if DEBUG_MACROS +%out s = v +endif +endif +endm + +_mkjmp macro is, in, label + local l + +;; +;; if pass 1 and label is already known, generate correct instruction +;; + +if1 +if (.type &label and DEFINED_BIT) + +;; +;; if label is too far away for short jump instruction, make jump <condition> +;; into jump <NOT condition> round jump to label followed by a near jump to +;; label +;; + +if (((&label - $) gt 129) or ((&label - $) lt -126)) + &in l ;; short jump, NOT condition + jmp &label ;; jump to where we want to go +else + &is &label ;; short jump +endif + +;; +;; if pass 1 and we don't know about the label yet, adjust the program +;; counter by the max. number of bytes taken up by this macro (5 - 2 for +;; short jump, 3 for near jump) +;; + +else + nop + nop + nop + nop + nop +endif + +;; +;; pass 2 - do same stuff as for pass 1 +;; + +else +if (((&label - $) gt 129) or ((&label - $) lt -126)) + if ((&label-$) gt 129) + _put <label distance>, %(&label-$) + else + _put <label distance>, %($-&label) + endif + &in l + jmp &label +else + +;; +;; label is within +127/-128 bytes of current instruction - generate short +;; jump instruction and put the program counter forward past the space +;; reserved during pass 1 +;; + + _put <label distance>, %(&label-$) + &is &label + nop + nop + nop +endif +endif +l: +endm + + + +oldjmps macro label +if2 +if (((&label - $) gt 127) or (($ - &label) lt -128)) + jmp short l + jmp &label +else + jmp short &label + org $+3 +endif +else +;; +;; if this is pass 1 just take up max amount of space so phases don't get +;; screwed +;; + org $+5 +endif +l: +endm diff --git a/private/nw/vwipxspx/tsr/debugmac.inc b/private/nw/vwipxspx/tsr/debugmac.inc new file mode 100644 index 000000000..45fe236e5 --- /dev/null +++ b/private/nw/vwipxspx/tsr/debugmac.inc @@ -0,0 +1,356 @@ +;++ +; +;Copyright (c) 1991 Microsoft Corporation +; +;Module Name: +; +; debugmac.inc +; +;Abstract: +; +; Contains debugging macros: +; +; DbgBreakPoint +; DbgUnsupported +; DbgDEBUG +; DbgPrint +; DbgPrintTty +; DbgPrintString +; DbgPrintHexDword +; DbgPrintHexWord +; DbgPrintHexByte +; DbgPrintNearPointer +; DbgPrintFarPointer +; +;Author: +; +; Richard L Firth (rfirth) 13-Sep-1991 +; +;Environment: +; +; DOS application mode only +; +;[Notes:] +; +; optional-notes +; +;Revision History: +; +; 13-Sep-1991 rfirth +; Created +; +;-- + + +;*** DbgBreakPoint +;* +;* Same as NT routine of same name. No-op in non-DEBUG version +;* +;* ENTRY +;* +;* EXIT +;* +;* RETURNS +;* +;* ASSUMES +;* +;*** + +DbgBreakPoint macro +if DEBUG + int 3 +endif +endm + +;*** DbgUnsupported +;* +;* Causes the 32-bit support code to display a message about an unsupported +;* service code, and dumps the 16-bit registers. Used to discover when an +;* unsupported int 2f/11 call or int 21/5f call is being made +;* +;* ENTRY +;* +;* EXIT +;* +;* RETURNS +;* +;* ASSUMES +;* +;*** + +DbgUnsupported macro +if DEBUG + SVC -1 +endif +endm + +;*** DbgDEBUG +;* +;* Prints the string "DEBUG: " to console using Bios Int 10h/ah=0eh +;* +;* ENTRY nothing +;* +;* EXIT nothing +;* +;* USES ax +;* +;* ASSUMES 286+ +;* +;*** + +DbgDEBUG macro + mov ax,(14 shl 8) + 'D' + int 10h + mov al,'E' + int 10h + mov al,'B' + int 10h + mov al,'U' + int 10h + mov al,'G' + int 10h + mov al,':' + int 10h + mov al,' ' + int 10h +endm + + + +;*** DbgCrLf +;* +;* Prints CR,LF to console using Bios Int 10h/ah=0eh +;* +;* ENTRY nothing +;* +;* EXIT nothing +;* +;* USES nothing +;* +;* ASSUMES 286+ +;* +;*** + +DbgCrLf macro + push ax + mov ax,(14 shl 8) + 13 + int 10h + mov al,10 + int 10h + pop ax +endm + + + +;*** DbgPrint +;* +;* Prints an ASCIZ string to console using Bios Int 10h +;* +;* ENTRY string - address of ASCIZ string to print +;* +;* EXIT nothing +;* +;* USES nothing +;* +;* ASSUMES 286+ +;* +;*** + +DbgPrint macro string +if DEBUG ;; no macro if not debug version + pushf ;; save regs used by DbgPrintTty + push ax + push bx + push si + push ds + mov ax,seg string + mov ds,ax + mov si,offset string;; ds:si = address of string + DbgPrintTty ;; display it on console + pop ds + pop si + pop bx + pop ax + popf +endif +endm + + + +;*** DbgPrintTty +;* +;* Prints an ASCIZ string in ds:si to console using Bios Int 10h +;* +;* ENTRY page - if present defines which Bios video page to use +;* Defaults to 0 +;* ds:si - address of ASCIZ string to print +;* +;* EXIT nothing +;* +;* USES al, bh, si, flags +;* +;* ASSUMES 286+ +;* +;*** + +DbgPrintTty macro page + local l1,l2 + +if DEBUG ;; no macro if not debug version + mov ah,14 ;; Bios Int write character as TTY function +ifb <page> + sub bh,bh +else + mov bh,page +endif + cld ;; autoincrement lodsb +l1: lodsb ;; al := next character; si := next character addr + or al,al ;; eof string? + jz l2 ;; yes + int 10h ;; display it to console + jmp short l1 ;; go round again +l2: +endif +endm + + + +;*** DbgPrintString +;* +;* Prints a string to console using Bios Int 10h. Note that this macro +;* does not do printf style substitutions. The string "DEBUG: " will be +;* displayed if the banner parm is not blank +;* +;* ENTRY string - character string. Needn't be zero-terminated +;* banner - the "DEBUG: " banner will be printed if not blank +;* +;* EXIT nothing +;* +;* USES nothing +;* +;* ASSUMES 286+ +;* +;*** + +DbgPrintString macro string, banner + local s1 + local l1 + +if DEBUG ;; no macro if not debug version + jmp short l1 +s1 db &string,0 +l1: pushf ;; don't destroy direction flag + pusha ;; save gp regs +ifb <banner> + DbgDEBUG ;; Display "DEBUG: " +endif + push ds ;; save user's data seg + push cs + pop ds ;; ds == cs + mov si,offset cs:s1 ;; si := string offset + DbgPrintTty ;; display ds:si to console + pop ds ;; restore user's data seg + popa ;; restore gp regs + popf ;; restore direction flag+ +endif +endm + + + +;*** DbgPrintHexDword +;* +;* Prints a dword to console in hex notation using Bios Int 10h +;* +;* ENTRY dword - dword to print +;* +;* EXIT nothing +;* +;* USES nothing +;* +;* ASSUMES 286+ +;* +;*** + +DbgPrintHexDword macro dword +if DEBUG ;; no macro if not debug version + DbgPrint <"DbgPrintHexDword not implemented yet",13,10> +endif +endm + + + +;*** DbgPrintHexWord +;* +;* Prints a word to console in hex notation using Bios Int 10h +;* +;* ENTRY word - to print. Can be memory or register +;* +;* EXIT nothing +;* +;* USES nothing +;* +;* ASSUMES 286+ +;* +;*** + +DbgPrintHexWord macro word + local l1, l2 +if DEBUG ;; no macro if not debug version + pushf ;; don't use any registers + push ax + push cx + push dx +ifdifi <word>,<ax> + mov ax,word +endif + mov cx,4 +l1: rol ax,4 + mov dx,ax + and al,0fh + cmp al,9 + jle l2 + add al,'a'-('9'+1) +l2: add al,'0' + mov ah,14 + int 10h + mov ax,dx + loop l1 + pop dx + pop cx + pop ax + popf +endif +endm + + + +;*** DbgPrintHexByte +;* +;* Prints a string to console using Bios Int 10h. Note that this macro +;* does not do printf style substitutions +;* +;* ENTRY string - character string. Needn't be zero-terminated +;* +;* EXIT +;* +;* USES nothing +;* +;* ASSUMES 286+ +;* +;*** + +DbgPrintHexByte macro byte +if DEBUG ;; no macro if not debug version + DbgPrint <"DbgPrintHexByte not implemented yet",13,10> +endif +endm + + + +DbgPrintNearPointer macro nearptr +endm + + + +DbgPrintFarPointer macro farptr +endm diff --git a/private/nw/vwipxspx/tsr/makefile b/private/nw/vwipxspx/tsr/makefile new file mode 100644 index 000000000..cd181de7d --- /dev/null +++ b/private/nw/vwipxspx/tsr/makefile @@ -0,0 +1,159 @@ +!IF 0 + +Copyright (c) 1991 & 1993 Microsoft Corporation + +Module Name: + + makefile + +Abstract: + + makefile for Vdm NetWare Redir program + +Author: + + Richard L Firth (rfirth) 13-Sep-1991 + +Revision History: + + 13-Sep-1991 rfirth + Created + +!ENDIF + + + +.SUFFIXES: +.SUFFIXES: .asm .h + +OBJPATH = obj + +ASM = masm +!IFDEF NTVDM_BASED_BUILD +LINK = link16 +!ELSE +LINK = link +!ENDIF + +# +# set the country info +# + +!IFNDEF COUNTRY +COUNTRY=usa +!ENDIF + +# +# convert NTDEBUG into DEBUG flag. NTDEBUG can be not present or retail, either +# of which mean no debugging; or ntsd, cvp or sym, which means debugging support +# required +# + +!IFDEF NTDEBUG +!IF "$(NTDEBUG)" == "retail" +DEBUGGING=0 +!ELSE +DEBUGGING=1 +!ENDIF +!ELSE +DEBUGGING=0 +!ENDIF + +# +# assembler and linker debugging options +# + +!IF $(DEBUGGING) +ASMDEBUG = /DDEBUG=1 /Zi +LINKDEBUG = /CO +!ELSE +ASMDEBUG = /DDEBUG=0 +LINKDEBUG = +!ENDIF +ASMINC = /I. /I..\..\inc /I..\..\..\mvdm\dos\v86\inc /I\nt\public\sdk\inc +ASMFLAGS = /Mx +LINKFLAGS = /MAP /CP:1 + +# +# any other non-debug related options (for assembler) go in USERDEFS +# + +USERDEFS = /DCALL_DOS + +# +# Inference rules - asm to obj, h to inc +# + +.asm{$(OBJPATH)\}.obj: + $(ASM) $(ASMINC) $(ASMDEBUG) $(USERDEFS) $<,$@; + +.h.inc: + h2inc $< -o $*.inc + +.asm.lst: + $(ASM) $(ASMINC) $(ASMDEBUG) $(USERDEFS) /d /L $<; + +# +# what it is we're building +# + +TARGET = $(OBJPATH)\vwipxspx.exe +MAPFILE = $(TARGET:.exe=.map) +DEFFILE = ; + +OBJS = $(OBJPATH)\vwipxspx.obj + +LIBS = + +# +# how to build it +# + +all: makedir $(TARGET) + +$(TARGET): $(OBJS) + $(LINK) @<< +$(OBJS) +$(TARGET) $(LINKFLAGS) $(LINKDEBUG) +$(MAPFILE) +$(LIBS) +$(DEFFILE) +<< + +# +# where to put it +# + + binplace $(TARGET) + +# +# clean build - delete all objs +# + +#clean: makedir clean2 +clean: clean2 + +clean2: + if exist $(OBJPATH)\*.obj del $(OBJPATH)\*.obj + $(MAKE) + +# +# makedir - ensure the subdirectory for the object files exists +# + +makedir: + @-if not exist $(OBJPATH) md $(OBJPATH) + +# +# file dependencies +# + +$(OBJPATH)\vwipxspx.obj:\ + vwipxspx.asm \ + debugmac.inc \ + asmmacro.inc \ + segorder.inc \ + messages.inc + +messages.inc: ..\..\inc\$(COUNTRY)\messages.inc + copy ..\..\inc\$(COUNTRY)\messages.inc . diff --git a/private/nw/vwipxspx/tsr/segorder.inc b/private/nw/vwipxspx/tsr/segorder.inc new file mode 100644 index 000000000..689c62fa2 --- /dev/null +++ b/private/nw/vwipxspx/tsr/segorder.inc @@ -0,0 +1,113 @@ +;/*++ +; +;Copyright (c) 1991 Microsoft Corporation +; +;Module Name: +; +; segorder.inc +; +;Abstract: +; +; This module contains the segment order and segment macros +; +;Author: +; +; Richard Firth (rfirth) 05-Sep-1991 +; +;Environment: +; +; Dos mode only +; +;Notes: +; +; When initially loaded, the NT VDM redir has the following order: +; +; +----------------------+ +; | | +; | Resident Code | +; | | +; +----------------------+ +; | | +; | Resident Data | +; | | +; +----------------------+ ----------------+ +; | | | +; | Initialisation Code | <- entry point v +; | | +; +----------------------+ +; | | all the stuff between these +; | Initialisation Data | arrows is discarded if we stay +; | | resident. Note that the redir +; +----------------------+ does not uninstall +; | | +; | Initialisation Stack | ^ +; | | | +; +----------------------+ ----------------+ +; +;Revision History: +; +; 05-Sep-1991 rfirth +; Created +; +;--*/ + + + +ResidentStart segment public para 'code' +ResidentStart ends + +ResidentCode segment public word 'code' +ResidentCode ends + +ResidentData segment public word 'data' +ResidentData ends + +ResidentEnd segment public para 'data' +ResidentEnd ends + +ResidentGroup group ResidentStart, ResidentCode, ResidentData, ResidentEnd + +InitCode segment public para 'init' +InitCode ends + +InitData segment public word 'init' +InitData ends + +InitStack segment stack para 'stack' +InitStack ends + +; +; macros to avoid having to type in/possibly alter segment header guff +; + +ResidentCodeStart macro +ResidentCode segment public word 'code' +endm + +ResidentCodeEnd macro +ResidentCode ends +endm + +ResidentDataStart macro +ResidentData segment public word 'data' +endm + +ResidentDataEnd macro +ResidentData ends +endm + +InitCodeStart macro +InitCode segment public para 'init' +endm + +InitCodeEnd macro +InitCode ends +endm + +InitDataStart macro +InitData segment public word 'init' +endm + +InitDataEnd macro +InitData ends +endm diff --git a/private/nw/vwipxspx/tsr/vwipxspx.asm b/private/nw/vwipxspx/tsr/vwipxspx.asm new file mode 100644 index 000000000..601f80c10 --- /dev/null +++ b/private/nw/vwipxspx/tsr/vwipxspx.asm @@ -0,0 +1,711 @@ +page ,132 +if 0 + +/*++ + +Copyright (c) 1993 Microsoft Corporation + +Module Name: + + vwipxspx.asm + +Abstract: + + Contains handlers for 16-bit (DOS) netware IPX/SPX emulation. Creates TSR + + Contents: + start + InstallationCheck + InstallVdd + InstallInterruptHandlers + VwIpxEntryPoint + VwIpxDispatcher + VwIpx7ADispatcher + DispatchWithFeeling + VwIpxEsrFunction + +Author: + + Richard L Firth (rfirth) 30-Sep-1993 + +Environment: + + DOS Real mode only + +Revision History: + + 30-Sep-1993 rfirth + Created + +--*/ + +endif + +; +; DOS include files +; + +.xlist +.xcref +include isvbop.inc ; NTVDM BOP mechanism +include dossym.inc ; includes MS-DOS version etc +include pdb.inc ; PSP defines +include syscall.inc ; AssignOper +include segorder.inc ; load order of 'redir' segments +include debugmac.inc ; debug display macros +include asmmacro.inc ; jumps which may be short or near +include messages.inc ; internationalisationable (prestidigitation) messages +.cref +.list + +InitStack segment stack para 'stack' + + dw 256 dup (?) + +InitStack ends + +InitDataStart + +bad_ver_msg db NLS_MSG_001,c_CR,c_LF +BAD_VER_MSG_LEN equ $-bad_ver_msg + db '$' ; for INT 21/09 display string + +already_loaded_msg db NLS_MSG_002,c_CR,c_LF +ALREADY_LOADED_MSG_LEN equ $-already_loaded_msg + +cannot_load_msg db NLS_MSG_003,c_CR, c_LF +CANNOT_LOAD_MSG_LEN equ $-cannot_load_msg + +; +; strings used to load/dispatch NWIPXSPX.DLL +; + +DllName db "VWIPXSPX.DLL",0 +InitFunc db "VwInitialize",0 +DispFunc db "VwDispatcher",0 + +InitDataEnd + +InitCodeStart + assume cs:InitCode + assume ds:nothing + assume es:nothing + assume ss:nothing + + public start +start proc near + +; +; when we start up we could be on any old PC - even an original, so don't +; assume anything other than a model-T processor +; + + .8086 + +; +; Set the data segment while we're at it - all paths set it sooner +; or later. NOTE: es will point to the PSP until we change it! +; + + mov dx,InitData + mov ds,dx + + assume ds:InitData + +; +; first off, get the DOS version. If we're not running on NT (VDM) then this +; TSR's not going to do much, so exit. Exit using various methods, depending +; on the DOS version (don't you hate compatibility?) +; + + mov ah,30h + int 21h + jc ancient_version ; version not even supported + +; +; version is 2.0 or higher. Check it out. al = major#, ah = minor# +; + + cmp al,major_version + jne invalid_version + +; +; okay, we're at least 5.0. But are we NT? +; + + mov ax,3306h + int 21h + jc invalid_version ; ? + cmp bl,5 + jne invalid_version + cmp bh,50 + jne invalid_version + +; +; what do you know? We're actually running on NT (unless some evil programmer +; has pinched int 21h/30h and broken it!). Enable minimum instruction set +; for NTVDM (286 on RISC). +; + + .286c + +; +; perform an installation check. Bail if we're there dude ((C) Beavis & Butthead) +; + + call InstallationCheck + jnz already_here ; nope - IPX/SPX support installed already + +; +; BUGBUG: we should find some way of deferring loading the 32-bit DLL until an +; IPX/SPX function is called, to speed-up loading. However, if we later find we +; cannot load the DLL, it may be too late: there is no way of consistently +; returning an error and we cannot unload the TSR +; + + call InstallVdd ; returns IRQ in BX + jc initialization_error + call InstallInterruptHandlers + + assume es:nothing + +; +; free the environment segment +; + + mov es,es:[PDB_environ] + mov ah,49h + int 21h ; free environment segment + +; +; finally terminate and stay resident +; + + mov dx,ResidentEnd + sub dx,ResidentStart ; number of paragraphs in resident code + add dx,10h ; additional for PSP (PDB) + mov ax,3100h + int 21h ; terminate and stay resident + +; +; here if the MS-DOS version check (Ah=30h) call is not supported +; + +ancient_version: + mov dx,InitData + mov ds,dx + + assume ds:InitData + + mov dx,offset bad_ver_msg + mov ah,9 ; cp/m-style write to output + int 21h + +; +; safe exit: what we really want to do here is INT 20H, but when you do this, +; CS must be the segment of the PSP of this program. Knowing that CD 20 is +; embedded at the start of the PSP, the most foolproof way of doing this is +; to jump (using far return) to the start of the PSP +; + + push es + xor ax,ax + push ax + retf ; terminate + +; +; we are running on a version of DOS >= 2.00, but its not NT, so we still can't +; help. Display the familiar message and exit, but using a less programmer- +; hostile mechanism +; + +invalid_version: + mov dx,offset bad_ver_msg + mov cx,BAD_VER_MSG_LEN + jmp short print_error_message_and_exit + +; +; if we cannot initialize 32-bit support (because we can't find/load the DLL) +; then put back the hooked interrupt vectors as they were when this TSR started, +; display a message and fail to load the redir TSR +; + +initialization_error: + mov dx,offset cannot_load_msg + mov cx,CANNOT_LOAD_MSG_LEN + jmp short print_error_message_and_exit + +; +; The DOS version's OK, but this TSR is already loaded +; + +already_here: + mov dx,offset already_loaded_msg + mov cx,ALREADY_LOADED_MSG_LEN + +print_error_message_and_exit: + mov bx,1 ; bx = stdout handle + mov ah,40h ; write to handle + int 21h ; write (cx) bytes @ (ds:dx) to stdout + mov ax,4c01h ; terminate program + int 21h ; au revoir, cruel environment + +start endp + +; *** InstallationCheck +; * +; * Test to see if this module is already loaded +; * +; * ENTRY nothing +; * +; * EXIT ZF = 0: loaded +; * +; * USES AX +; * +; * ASSUMES nothing +; * +; *** + +InstallationCheck proc + mov ax,7a00h + int 2fh + or al,al + ret +InstallationCheck endp + +; *** InstallVdd +; * +; * Load VWIPXSPX.DLL into the NTVDM process context +; * +; * ENTRY nothing +; * +; * EXIT CF = 1: error +; * CF = 0: VWIPXSPX loaded ok +; * AX = VDD handle +; * BX = IRQ used by call-back functions (ESR) +; * ResidentCode:VddHandle updated +; * ResidentCode:IrqValue updated +; * +; * USES AX, BX, SI, DI +; * +; * ASSUMES nothing +; * +; *** + +InstallVdd proc + push ds + push es + mov ax,InitData + mov ds,ax + + assume ds:InitData + + mov es,ax + mov si,offset DllName ; ds:si = library name + mov di,offset InitFunc ; es:di = init function name + mov bx,offset DispFunc ; ds:bx = dispatcher function name + + RegisterModule ; returns carry if problem + + mov si,ResidentCode + mov ds,si + + assume ds:ResidentCode + + mov VddHandle,ax + mov IrqValue,bx + pop es + + assume es:nothing + + pop ds + + assume ds:nothing + + ret +InstallVdd endp + +; *** InstallInterruptHandlers +; * +; * Sets the interrupt handlers for all the ints we use - 2F, 7A +; * +; * ENTRY BX = IRQ for call-backs +; * ES = PSP segment +; * +; * EXIT Old2FHandler contains the original interrupt 2F vector +; * Old7AHandler contains the original interrupt 7A vector +; * OldIrqHandler contains original IRQ vector +; * +; * USES AX, BX, CX, DX +; * +; * ASSUMES nothing +; * +; *** + +InstallInterruptHandlers proc + push es ; PSP segment - destroyed by INT 21/35h + push ds + mov dx,ResidentCode + mov ds,dx + + assume ds:ResidentCode + +; +; get and set call-back IRQ +; + + mov ah,35h + mov al,bl + mov cl,bl ; cl = IRQ number + int 21h + mov word ptr OldIrqHandler,bx + mov word ptr OldIrqHandler+2,es + mov al,cl + mov ah,25h + mov dx,offset ResidentCode:VwIpxEsrFunction + int 21h + +; +; get and set 2F handler +; + + mov ax,352Fh + int 21h + mov word ptr Old2FHandler,bx + mov word ptr Old2FHandler+2,es + mov dx,offset ResidentCode:VwIpxEntryPoint + mov ax,252Fh + int 21h + +; +; get and set 7A handler +; + + mov ax,357Ah + int 21h + mov word ptr Old7AHandler,bx + mov word ptr Old7AHandler+2,es + mov dx,offset ResidentCode:VwIpx7ADispatcher + mov ax,257Ah + int 21h + pop ds ; restore segment registers + + assume ds:nothing + + pop es + + assume es:nothing + + ret +InstallInterruptHandlers endp + +InitCodeEnd + +page + +; +; code from here on will be left in memory after initialisation +; + +ResidentCodeStart + + assume cs:ResidentCode + assume ds:nothing + assume es:nothing + assume ss:nothing + +Old2FHandler dd ? +Old7AHandler dd ? +OldIrqHandler dd ? + +IrqValue dw ? + +VddHandle dw ? + +; *** VwIpxEntryPoint +; * +; * The INT 2Fh handler that recognizes the Netware IPX request code (7A). +; * Also chains INT 2F/AX=1122 +; * +; * ENTRY AX = 7A00h +; * +; * EXIT AL = 0FFh +; * ES:DI = address of routine to call when submitting IPX/SPX +; * requests +; * +; * USES +; * +; * ASSUMES nothing +; * +; *** + +VwIpxEntryPoint proc + cmp ax,7a00h + jne @f + mov di,cs + mov es,di + mov di,offset VwIpxDispatcher + dec al + iret + +; +; not 7A00h. Check for 1122h (IFSResetEnvironment). If yes, then this is DOS +; calling the IFS chain to notify that the app is terminating. When we have +; notified the DLL, chain the IFS request +; + +@@: cmp ax,7affh + jne try1122 + mov di,cs + mov es,di + mov di,offset VwIpxDispatcher + or bx,bx + jz @f + mov cx,8000h + mov si,7 + iret +@@: mov cx,14h + mov si,200h + iret + +try1122:cmp ax,1122h + jne @f + +; +; DOS Calls INT 2F/AX=1122 for every terminating app, including this one. We +; can't differentiate between a TSR and a non-TSR. Let the DLL handle it +; + + push ax + push bx + push cx + mov ah,51h + int 21h + mov cx,bx ; cx = PDB of terminating program/TSR + mov bx,-1 ; bx = dispatch code + mov ax,VddHandle ; ax = VDD handle + DispatchCall + pop cx + pop bx + pop ax +@@: jmp Old2FHandler ; chain int 2F +VwIpxEntryPoint endp + +; *** VwIpxDispatcher +; * +; * All DOS IPX/SPX calls are routed here by the netware libraries. Just +; * BOP on through to the other side +; * +; * This routine just transfers control to 32-bit world, where all work is +; * done +; * +; * ENTRY BX = netware IPX/SPX dispatch code +; * others - depends on function +; * +; * EXIT depends on function +; * +; * USES depends on function +; * +; * ASSUMES nothing +; * +; *** + +VwIpxDispatcher proc far + pushf ; apparently we don't modify flags + call DispatchWithFeeling + popf + ret +VwIpxDispatcher endp + +; *** VwIpx7ADispatcher +; * +; * Older Netware apps make the call to IPX/SPX via INT 7A. Same function +; * as VwIpxDispatcher +; * +; * This routine just transfers control to 32-bit world, where all work is +; * done +; * +; * ENTRY BX = netware IPX/SPX dispatch code +; * others - depends on function +; * +; * EXIT depends on function +; * +; * USES depends on function +; * +; * ASSUMES nothing +; * +; *** + +VwIpx7ADispatcher proc + call DispatchWithFeeling + iret +VwIpx7ADispatcher endp + +; *** DispatchWithFeeling +; * +; * Performs the dispatch for VrIpxDispatcher and VrIpx7ADispatcher. Checks +; * requested function for return code in AX: either returns value in AX +; * or restores AX to value on input +; * +; * This routine just transfers control to 32-bit world, where all work is +; * done +; * +; * ENTRY BX = netware IPX/SPX dispatch code +; * others - depends on function +; * +; * EXIT depends on function +; * +; * USES depends on function +; * +; * ASSUMES 1. Dispatch codes are in range 0..255 (ie 0 in BH) +; * +; *** + +DispatchWithFeeling proc + push bp + push ax ; caller value + +; +; some APIs (IPXOpenSocket, IPXScheduleIPXEvent, SPXEstablishConnection, and +; others...) pass a parameter in AX. Since AX is being used for the VDD +; handle, we have to commandeer another register to hold our AX value. BP is +; always a good candidate +; + + mov bp,ax ; grumble, mutter, gnash, gnash + push cx ; required if IPXOpenSocket + push bx ; dispatch code + or bx,bx ; IPXOpenSocket? + jz @f ; yus ma'am + cmp bl,3 ; IPXSendPacket? + jz @f ; yus ma'am again + jmp short carry_on_dispatching ; ooo-err missus + +; +; IPXOpenSocket et IPXSendPacket: We need an extra piece of info - the PDB of +; the process making this request. This is so we can clean-up at program +; termination +; + +@@: push bx + mov ah,51h ; get DOS PDB + int 21h ; this call can be made any time + mov cx,bx + pop bx + +carry_on_dispatching: + mov ax,VddHandle + DispatchCall + mov bp,sp + +; +; BX and [BP] will be the same value except for SPXInitialize which is the only +; function that returns something in BX +; + + xchg bx,[bp] ; bx = dispatch code, [bp] = returned bx + +; +; if this call returns something in AX (or AL) don't pop the AX value we pushed. +; If not a call which returns something in AX then restore the caller's AX. You +; can rest assured some assembler programmer has made use of the fact that some +; calls modify AX and the others leave it alone (presumably...?) +; + + or bl,bl ; 0x00 = IPXOpenSocket + jz @f + cmp bl,2 ; 0x02 = IPXGetLocalTarget + jz @f + cmp bl,4 ; 0x04 = IPXListenForPacket + jz @f + cmp bl,6 ; 0x06 = IPXCancelEvent + jz @f + cmp bl,8 ; 0x08 = IPXGetIntervalMarker + jz @f + cmp bl,10h ; 0x10 = SPXInitialize + jz spx_init + cmp bl,11h ; 0x11 = SPXEstablishConnection + jz @f + cmp bl,15h ; 0x15 = SPXGetConnectionStatus + jz @f + cmp bl,1ah ; 0x1A = IPXGetMaxPacketSize + jz @f + pop cx ; original dispatch code + pop cx ; original cx + pop ax ; original ax + pop bp ; original bp + ret + +; +; here if this call returns something in AX/AL +; + +@@: pop cx ; original dispatch code + pop cx ; original cx + pop bp ; don't restore AX + pop bp + ret + +; +; here if the call was SPXInitialize which returns values in AX, BX, CX, DX +; + +spx_init: + pop bx ; bx = major/minor SPX version # + pop bp ; caller cx - NOT restored + pop bp ; caller ax - NOT restored + pop bp ; caller bp - restored + ret +DispatchWithFeeling endp + +; *** VwIpxEsrFunction +; * +; * This routine makes the call to the ESR as defined in the ECB. We must +; * set up our stack, save the registers (except SS & SP), then call the +; * ESR. +; * +; * Control will not be transferred here for an ECB which has a NULL ESR +; * field +; * +; * ENTRY AL = 0 for AES or 0FFh for IPX +; * ES:SI = ECB address +; * +; * EXIT depends on function +; * +; * USES depends on function +; * +; * ASSUMES nothing +; * +; *** + +VwIpxEsrFunction proc + +; +; Novell documentation states all registers except SS and SP are saved before +; calling ESR and that INTERRUPTS ARE DISABLED +; + + pusha + push ds + push es + mov ax,VddHandle + mov bx,-2 + DispatchCall ; get ECB + jc @f + call dword ptr es:[si][4] ; branch to the ESR + mov al,20h + out 0a0h,al ; clear slave pic + out 20h,al ; " master " + pop es + pop ds + popa + iret +@@: pop es + pop ds + popa + jmp OldIrqHandler +VwIpxEsrFunction endp + +ResidentCodeEnd + +end start |