|
|
page ,132 if 0
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
resident.asm
Abstract:
This module contains the resident code part of the stub redir TSR for NT VDM net support. The routines contained herein are the 2f handler and the API support routines:
MultHandler ReturnMode SetMode GetAssignList DefineMacro BreakMacro GetRedirVersion NetGetUserName DefaultServiceError NetGetEnumInfo NetSpoolStuff
Author:
Richard L Firth (rfirth) 05-Sep-1991
Environment:
Dos mode only
Revision History:
05-Sep-1991 rfirth Created
--*/
endif
.xlist ; don't list these include files .xcref ; turn off cross-reference listing include dosmac.inc ; Break macro etc (for following include files only) include dossym.inc ; User_<Reg> defines include mult.inc ; MultNET include error.inc ; DOS errors - ERROR_INVALID_FUNCTION include syscall.inc ; DOS system call numbers include rdrint2f.inc ; redirector Int 2f numbers include segorder.inc ; segments include enumapis.inc ; dispatch codes include debugmac.inc ; DbgPrint macro include localmac.inc ; DbgPrint macro include asmmacro.inc ; language extensions include rdrsvc.inc ; BOP and SVC macros/dispatch codes include rdrmisc.inc ; miscellaneous definitions include sf.inc ; SFT definitions/structure include vrdefld.inc ; VDM_LOAD_INFO .cref ; switch cross-reference back on .list ; switch listing back on subttl ; kill subtitling started in include file
.286 ; all code in this module 286 compatible
ResidentDataStart public LanRootLength, LanRoot
LanRootLength dw ? ; can't be >81 bytes anyhow LanRoot db (64+3+1+13) dup (?)
ResidentDataEnd
ResidentCodeStart extrn DosQnmPipeInfo: near extrn DosQNmpHandState: near extrn DosSetNmpHandState: near extrn DosPeekNmPipe: near extrn DosTransactNmPipe: near extrn DosCallNmPipe: near extrn DosWaitNmPipe: near extrn NetTransactAPI: near extrn NetIRemoteAPI: near extrn NetUseAdd: near extrn NetUseDel: near extrn NetUseEnum: near extrn NetUseGetInfo: near extrn NetServerEnum: near extrn DosMakeMailslot: near extrn DosDeleteMailslot: near extrn DosMailslotInfo: near extrn DosReadMailslot: near extrn DosPeekMailslot: near extrn DosWriteMailslot: near extrn NetNullTransactAPI: near extrn NetServerEnum2: near extrn NetServiceControl: near extrn NetWkstaGetInfo: near extrn NetWkstaSetInfo: near extrn NetMessageBufferSend: near extrn NetHandleGetInfo: near extrn NetHandleSetInfo: near extrn DosReadAsyncNmPipe: near extrn DosWriteAsyncNmPipe: near extrn DosReadAsyncNmPipe2: near extrn DosWriteAsyncNmPipe2: near extrn MessengerDispatch: near
; ; IMPORTANT: This structure MUST be the first thing in the resident code segment ;
extrn dwPostRoutineAddress: dword
VdmWindowAddr VDM_LOAD_INFO <dwPostRoutineAddress, 0>
align 4
; ; Address of previous handler to chain if int 2f not for us ;
public OldMultHandler OldMultHandler dd ?
; ; OldFunctionTable is a table of near pointers to handlers for the old 5f ; functions 5f00 through 5f05 ;
OldFunctionTable label word dw ReturnMode ; 5f00 dw SetMode ; 5f01 dw GetAssignList ; 5f02 dw DefineMacro ; 5f03 dw BreakMacro ; 5f04 dw GetAssignList2 ; 5f05
; ; May as well keep this jump table in the code segment - no point in loading ; ds just to get a jump offset ;
MultDispatchTable label word dw GetRedirVersion ; 5f30 dw DefaultServiceError ; 5f31 - NetWkstaSetUID dw DosQnmPipeInfo ; 5f32 dw DosQNmpHandState ; 5f33 dw DosSetNmpHandState ; 5f34 dw DosPeekNmPipe ; 5f35 dw DosTransactNmPipe ; 5f36 dw DosCallNmPipe ; 5f37 dw DosWaitNmPipe ; 5f38 dw DefaultServiceError ; 5f39 - DosRawReadNmPipe dw DefaultServiceError ; 5f3a - DosRawWriteNmPipe dw NetHandleSetInfo ; 5f3b dw NetHandleGetInfo ; 5f3c dw NetTransactAPI ; 5f3d dw DefaultServiceError ; 5f3e - NetSpecialSMB dw NetIRemoteAPI ; 5f3f dw NetMessageBufferSend ; 5f40 dw DefaultServiceError ; 5f41 - NetServiceEnum dw NetServiceControl ; 5f42 dw DefaultServiceError ; 5f43 - DosPrintJobGetID dw NetWkstaGetInfo ; 5f44 dw NetWkstaSetInfo ; 5f45 dw NetUseEnum ; 5f46 dw NetUseAdd ; 5f47 dw NetUseDel ; 5f48 dw NetUseGetInfo ; 5f49 dw DefaultServiceError ; 5f4a - NetRemoteCopy dw DefaultServiceError ; 5f4b - NetRemoteMove dw NetServerEnum ; 5f4c dw DosMakeMailslot ; 5f4d dw DosDeleteMailslot ; 5f4e dw DosMailslotInfo ; 5f4f dw DosReadMailslot ; 5f50 dw DosPeekMailslot ; 5f51 dw DosWriteMailslot ; 5f52 dw NetServerEnum2 ; 5f53 dw NetNullTransactAPI ; 5f54 - NullTransaction entrypoint.
MAX_TABLE_ENTRIES = (($-MultDispatchTable)/type MultDispatchTable)-1
; ; this next table dispatches the functions that come in through a direct call ; to int 2f, ah=11, al=function code ;
ServiceDispatchTable label word dw NetGetUserName ; 80h - NetGetUserName o dw DefaultServiceError ; 81h - NetSetUserName x dw DefaultServiceError ; 82h - NetServiceNotify x dw DefaultServiceError ; 83h - NetPrintNameEnum x dw NetGetEnumInfo ; 84h - NetGetEnumInfo o dw DefaultServiceError ; 85h - TestDBCSLB x dw DosReadAsyncNmPipe ; 86h - DosReadAsyncNmPipe x dw DefaultServiceError ; 87h - DosUnusedFunction1 x dw DefaultServiceError ; 88h - DosUnusedFunction2 x dw DefaultServiceError ; 89h - NetCalloutNCB x dw DefaultServiceError ; 8Ah - EncrPasswd x dw DefaultServiceError ; 8Bh - NetGetLogonServer o dw DefaultServiceError ; 8Ch - NetSetLogonServer o dw DefaultServiceError ; 8Dh - NetGetDomain o dw DefaultServiceError ; 8Eh - NetSetDomain o dw DosWriteAsyncNmPipe ; 8FH - DosWriteAsyncNmPipe x dw DosReadAsyncNmPipe2 ; 90H - DosReadAsyncNmPipe2 x dw DosWriteAsyncNmPipe2 ; 91H - DosWriteAsyncNmPipe2 x
MAX_SERVICE_ENTRIES = (($-ServiceDispatchTable)/type ServiceDispatchTable)-1
page ; *** MultHandler ; * ; * Whenever an INT 2F call is made, sooner or later this function will ; * get control. If the call is actually for the redir, AH will be set ; * to 11h (MultNET). If it is any other value then we just chain it ; * along. Note that since there is no MINSES loaded in the NT DOS network ; * stack, then we need also to fake calls to MINSES. These are made through ; * INT 2F, with ah = 0xB8. We trap calls AX=B800 (network presence test) ; * and AX=B809 (network/redir installation test) ; * ; * ENTRY ax = (MultNET << 8) | net operation code ; * Net operation code can be: ; * Install check 0 ; * Assign operation 30 ; * Anything else is DOS/NET specific. We should raise a gorbachev ; * or rather an error if we receive something else ; * ; * Stack: IP \ ; * CS > From Int 2f ; * Flags / ; * Caller's AX From call to Int 21/ah=5f ; * ; * We need the caller's AX to dispatch the NetAssOper calls, nothing ; * more ; * ; * All the rest of the registers are as per the caller ; * ; * EXIT CF = 0 ; * success ; * CF = 1 ; * AX = error ; * ; * USES all regs ; * ; * ASSUMES Earth is flat ; * ; ***
if DEBUG OriginalAx dw ? OriginalBx dw ? endif
public MultHandler MultHandler proc far assume cs:ResidentCode assume ds:nothing assume es:nothing assume ss:nothing
if DEBUG mov OriginalAx,ax mov OriginalBx,bx endif cmp ah,MultNET ; 11h je @f
; ; test for AH=B8 and return network presence indicators if it is. Here we are ; faking calls to MINSES (minimum session layer) and intercept calls AX=B800 ; and AX=B809. Any other AH=B8 call must be for a different TSR/driver ;
cmp ah,0b8h jne check_messenger or al,al jnz try_9
; ; AX=B800. This is the MinSes installation check. Return the magic numbers ; AL=1 and BX=8 (see doslan\minses\int2f.inc in LANMAN project) ;
inc al mov bx,8 do_iret:iret
try_9: cmp al,9 jne chain_previous_handler ; AL not 0 or 9, AH=B8 for somebody else
; ; AX=B809 is a network installation test. Return the magic numbers AL=1, AH=2 ; for PC Network version 1.2 (this is what minses does, don't complain to me ; about PC networks, etc, etc) ;
mov ax,0201h jmp short do_iret
; ; MESSENGER TSR uses AH=42h ;
check_messenger: cmp ah,42h ; multMESSAGE jne chain_previous_handler call MessengerDispatch retf 2 ; return state in flags
chain_previous_handler: jmp OldMultHandler ; not for us; pass it along
; ; the 2f call is for us. If it is the installation check, return al == -1 else ; dispatch the byte code at sp+6 ;
@@: sti ; re-enable interrupts or al,al jnz @f or al,-1 ; installation check just returns 0xff ret 2 ; 'or' clears carry
@@: cld ; auto-increment string operations
; ; this call is something other than an installation check. I really hope that ; its the AssignOper request, because I don't know what to do if it isn't... ;
cmp al,_2F_NET_ASSOPER jmpe is_net_request ; yes - we can do something
; ; if its the ResetEnvironment request then we have to kill any net state info ; like mailslot info. Return via iret ;
cmp al,_2F_NetResetEnvironment jmpne check_service_call
; ; deferred loading: don't load VDMREDIR.DLL for VrTerminateDosProcess if no NET ; calls have been made ;
cmp VdmWindowAddr.VrInitialized,1 je @f iret
if 0 DbgPrintString "NetResetEnvironment received. PDB=" push ax ; int 21/51 uses ax,bx push bx endif
@@: mov ah,51h int 21h ; get current PDB
if 0 DbgPrintHexWord bx ; bx contains PSP of current process pop bx pop ax DbgCrLf endif
mov ax,bx SVC SVC_RDRTERMINATE iret
; ; if this is a net service call (ah=11h, al=function code 80h through 91h) then ; dispatch through the service table ;
check_service_call: cmp al,_2F_NetSpoolOper ; 25h jne @f call NetSpoolStuff jmp short return_to_dos @@: cmp al,_2F_NetGetUserName ; 80h jmpb trap_it cmp al,_2F_DosWriteAsyncNmPipe2 ; 91h jmpa trap_it
if 0 DbgPrintString "Received Service Request: " DbgPrintHexWord ax DbgCrLf endif
sub ax,(MultNET shl 8) + _2F_NetGetUserName xchg ax,bx shl bx,1 mov bx,ServiceDispatchTable[bx] xchg ax,bx call ax
; ; all calls that come through here are expected to have originated in DOS ;
return_to_dos: ret 2 ; with interrupts enabled ; ; if we get anything else, either from DOS, or some - as yet - unknown source, ; then just pass it along to the next handler. In the debug version, we alert ; someone to the fact that we've got an unrecognized call ;
trap_it: DbgPrintString "Received unrecognized Service Request: " DbgPrintHexWord ax DbgCrLf DbgBreakPoint
jmp OldMultHandler ; pass it down the chain
; ; get the original dispatch code back off the stack. We no longer require the ; current contents of ax ;
is_net_request: push bp mov bp,sp mov ax,[bp + 8] ; ax <- original code (5fxx) pop bp
if DEBUG mov OriginalAx,ax endif
; ; quick sanity check to make sure that we're processing the right call. If we ; were called with ax != 5fxx, assume that somebody else is also using the ; same 2F function call, and chain the next handler. Note: this wouldn't be ; a very smart thing to do ;
sub ah,AssignOper ; ah => 0 it is AssignOper jz @f DbgBreakPoint mov ax,(MultNET shl 8) + _2F_NET_ASSOPER ; restore ax jmps chain_previous_handler
@@: cmp al,5 ; is it 5f00 - 5f05? jnbe @f
; ; if the function is in the range 0 - 5 then its an old function - dispatch ; through the old function table ;
shl al,1 xchg ax,bx mov bx,OldFunctionTable[bx] xchg ax,bx call ax ret 2
@@: sub al,Local_API_RedirGetVersion jz @f ; function is GetRedirVersion cmp al,MAX_TABLE_ENTRIES jbe @f ; UNSIGNED comparison!!!
; ; get 32-bit support code to dump registers to debug terminal ;
if DEBUG mov ax,OriginalAx DbgUnsupported endif
mov ax,ERROR_NOT_SUPPORTED stc ; set error indication jmp short set_ax_exit
; ; the function is within range. Dispatch it. Copy the offset from the dispatch ; table into ax then call through ax. ax was only required to get us this far ; and contains no useful information ;
@@: xchg ax,bx ; need base register, ax not good enough in 286 shl bx,1 ; bx is now offset in dispatch table mov bx,MultDispatchTable[bx]; bx is offset of handler routine xchg ax,bx ; restore caller's bx call ax ; go handle it ret 2 ; return without reinstating flags
; ; Return an error in the caller's ax register. To do this we have to ask DOS to ; please give us the address of its copy of the user's registers, which it will ; pass back in DS:SI. We then futz with the copy of the user's reg. Dos will ; restore this before returning control to the user code. Since we know we have ; an error situation set the carry flag ;
set_ax_exit: pushf ; error indicator push ax ; return code DosCallBack GET_USER_STACK ; get pointer to caller's context
assume ds:nothing ; nuked - actually in DOS somewhere (stack)
pop [si].User_Ax ; copy saved return code into user's copy popf ; restore error indicator ret 2 ; clear caller's flags from int 2f call MultHandler endp
page ; *** ReturnMode ; * ; * Returns the disk or print redirection flag. Flag is 0 if redirection ; * is paused, else 1 ; * ; * ENTRY BL = 3 ; * Return print redirection ; * ; * BL = 4 ; * Return drive redirection ; * ; * EXIT CF = 0 ; * BX = redirection flag: 0 or 1 ; * ; * CF = 1 ; * error ; * ; * USES bx ; * ; * ASSUMES nothing ; * ; ***
PrintRedirection db 0 DriveRedirection db 0
ReturnMode proc near assume cs:ResidentCode assume ds:nothing
DbgPrintString <"5f00 called",13,10> DbgUnsupported
cmp bl,3 jne @f mov bh,PrintRedirection jmp short set_info @@: cmp bl,4 stc jnz @f mov bh,DriveRedirection set_info: and bh,1 DosCallBack GET_USER_STACK mov [si].User_Bx,bx clc @@: ret ReturnMode endp
page ; *** SetMode ; * ; * Pauses or continues drive or printer redirection. Note that we don't ; * support drive/print pause/continuation from DOS ; * ; * ENTRY BL = printer (3) or drive (4) redirection ; * BH = pause (0) or continue (1) ; * ; * EXIT CF = 0 ; * success ; * CF = 1 ; * ax = ERROR_INVALID_PARAMETER ; * ; * USES ax, bx ; * ; * ASSUMES nothing ; * ; ***
SetMode proc near assume cs:ResidentCode assume ds:nothing
DbgPrintString <"5f01 called",13,10> DbgUnsupported
cmp bh,1 jnbe bad_parm_exit dec bh ; convert 0 => ff, 1 => 0 not bh ; convert ff => 0, 0 => ff sub bl,3 jnz try_drive mov PrintRedirection,bh jmp short ok_exit try_drive: dec bl jnz bad_parm_exit mov DriveRedirection,bh ok_exit:clc ret bad_parm_exit: mov ax,ERROR_INVALID_PARAMETER stc ret SetMode endp
page ; *** GetAssignList ; * ; * Returns information on enumerated redirections. Old version of ; * NetUseGetInfo ; * ; * ENTRY BX = which item to return (starts @ 0) ; * DS:SI points to local redirection name ; * ES:DI points to remote redirection name ; * AL != 0 means return LSN in BP (GetAssignList2)? ** UNSUPPORTED ** ; * ; * EXIT CF = 0 ; * BL = macro type (3 = printer, 4 = drive) ; * BH = 'interesting' bits: 00 = valid, 01 = invalid ; * CX = user word ; * DS:SI has device type ; * ES:DI has net path ; * CF = 1 ; * AX = ERROR_NO_MORE_FILES ; * ; * USES ; * ; * ASSUMES nothing ; * ; ***
GetAssignList proc near assume cs:ResidentCode assume ds:nothing
xor al,al jmp short @f GetAssignList2: or al,-1 @@: SVC SVC_RDRGET_ASG_LIST jc @f push bx push cx DosCallBack GET_USER_STACK pop [si].User_Cx pop [si].User_Bx clc @@: ret GetAssignList endp
page ; *** DefineMacro ; * ; * Old version of NetUseAdd ; * ; * ENTRY BL = device type ; * 3 = printer ; * 4 = drive ; * bit 7 on means use the wksta password when connecting ; * CX = user word ; * DS:SI = local device ; * Can be NUL device name, indicating UNC use ; * ES:DI = remote name ; * ; * EXIT CF = 0 ; * success ; * ; * CF = 1 ; * AX = ERROR_INVALID_PARAMETER (87) ; * ERROR_INVALID_PASSWORD (86) ; * ERROR_INVALID_DRIVE (15) ; * ERROR_ALREADY_ASSIGNED (85) ; * ERROR_PATH_NOT_FOUND (3) ; * ERROR_ACCESS_DENIED (5) ; * ERROR_NOT_ENOUGH_MEMORY (8) ; * ERROR_NO_MORE_FILES (18) ; * ERROR_REDIR_PAUSED (72) ; * ; * USES ; * ; * ASSUMES nothing ; * ; ***
DefineMacro proc near assume cs:ResidentCode assume ds:nothing
SVC SVC_RDRDEFINE_MACRO ret DefineMacro endp
page ; *** BreakMacro ; * ; * Old version of NetUseDel ; * ; * ENTRY DS:SI = buffer containing device name of redirection to break ; * ; * EXIT ; * ; * USES ; * ; * ASSUMES nothing ; * ; ***
BreakMacro proc near assume cs:ResidentCode assume ds:nothing
SVC SVC_RDRBREAK_MACRO ret BreakMacro endp
page ; *** GetRedirVersion ; * ; * Returns the version number of this redir in ax ; * ; * ENTRY none ; * ; * EXIT ax = version # ; * ; * USES ax, flags ; * ; * ASSUMES nothing ; * ; ***
GetRedirVersion proc near assume cs:ResidentCode assume ds:nothing
mov ax,300 clc ret GetRedirVersion endp
page ; *** NetGetUserName ; * ; * Returns the current logged on user name (if any) ; * ; * ENTRY CX = buffer length ; * ES:DI = buffer ; * ; * EXIT CF = 1 ; * AX = Error code ; * NERR_BufTooSmall ; * Buffer not large enough for user name ; * ; * CF = 0 ; * CX:BX = UID (ignored) ; * ES:DI = user name ; * ; * USES ax, flags ; * ; * ASSUMES nothing ; * ; ***
NetGetUserName proc near assume cs:ResidentCode assume ds:nothing
mov bx,1 ; bx == 1: check name length against cx call NetGetUserNameSvcCall
DbgBreakPoint
jc @f ; error
; ; no error: the user name was copied into ES:DI. Set the caller's cx and bx to ; return a UID. We could leave this as a random number since it is not used, ; but we set it to a known value ;
DosCallBack GET_USER_STACK xor ax,ax ; clears carry again mov [si].User_Cx,ax inc ax mov [si].User_Bx,ax ; UID = 0x00000001 @@: ret NetGetUserName endp
page ; *** DefaultServiceError ; * ; * Default error routine - returns ERROR_INVALID_FUNCTION for any API ; * function which we don't support. Reached exclusively through dispatch ; * table ; * ; * ENTRY none ; * ; * EXIT CF = 1 ; * AX = ERROR_INVALID_FUNCTION ; * ; * USES ax, flags ; * ; * ASSUMES nothing ; * ; ***
DefaultServiceError proc near assume cs:ResidentCode assume ds:nothing
; DbgPrintString <"DefaultServiceError Ax=" ; DbgPrintHexWord OriginalAx ; DbgPrintString <" Bx=">,NOBANNER ; DbgPrintHexWord OriginalBx ; DbgCrLf
; ; cause debug output to go to debug port: making invalid BOP will dump registers ;
if DEBUG mov ax,OriginalAx mov bx,OriginalBx DbgUnsupported endif mov ax,ERROR_INVALID_FUNCTION stc ret DefaultServiceError endp
page ; *** NetGetEnumInfo ; * ; * Routine which returns various internal redir variables based on an ; * index ; * ; * ENTRY BL = index ; * 0 = CDNames ; * 1 = Comment (not supported) ; * 2 = LanRoot ; * 3 = ComputerName ; * 4 = UserName ; * 5 = Primary Domain ; * 6 = Logon Server ; * 7 = Mailslots Yes/No ; * 8 = RIPL Yes/No ; * 9 = Get RIPL UNC ; * 10 = Get RIPL drive ; * 11 = Start marking CON_RIPL ; * 12 = Stop marking CON_RIPL ; * 13 = exchange int17 handlers ; * 14 = primary WrkNet ; * ; * es:di = buffer for returned info ; * ; * EXIT CF = 0 ; * success ; * CF = 1 ; * AX = ERROR_INVALID_FUNCTION ; * ; * USES ax, flags ; * ; * ASSUMES nothing ; * ; ***
NetGetEnumInfo proc near or bl,bl jnz @f
; ; CDNames (Computer and Domain Names) ;
; DbgPrintString <"NetGetEnumInfo: return CDNames", 13, 10> SVC SVC_RDRGETCDNAMES ret
; ; Comment - nothing returned by this or the original redir (ax = invalid ; function, but carry clear?) ;
@@: dec bl jnz @f DbgPrintString <"NetGetEnumInfo: return Comment", 13, 10> mov ax,ERROR_INVALID_FUNCTION ret
; ; LanRoot ;
@@: dec bl jnz check_computername DbgPrintString <"NetGetEnumInfo: return LanRoot", 13, 10> pusha ; save user gp regs push es ; save user seg regs push ds mov si,ResidentData mov ds,si assume ds:ResidentData mov si,offset LanRoot mov cx,LanRootLength shr cx,1 ; cx = number of words to copy, cf=lsb cld rep movsw ; copy words jnc @f ; if not odd number of bytes skip movsb ; copy single byte @@: pop ds ; restore user seg regs pop es popa ; restore user gp regs ret
; ; ComputerName ;
check_computername: dec bl jnz @f DbgPrintString <"NetGetEnumInfo: return ComputerName", 13, 10> SVC SVC_RDRGETCOMPUTERNAME ret ; ; Username ;
@@: dec bl jnz @f DbgPrintString <"NetGetEnumInfo: return UserName", 13, 10>
; ; This is also the entry point for NetGetUserName, which return some info in ; cx:bx (the (ignored) UID). We could leave this random, but we set it to a ; known value, just in case ;
NetGetUserNameSvcCall: SVC SVC_RDRGETUSERNAME ; either 0 if for NetGetEnumInfo or 1 if NetGetUserName ret
; ; Primary domain name ;
@@: dec bl jnz @f DbgPrintString <"NetGetEnumInfo: return DomainName", 13, 10> SVC SVC_RDRGETDOMAINNAME ret
; ; Logon server name ;
@@: dec bl jnz @f DbgPrintString <"NetGetEnumInfo: return LogonServerName", 13, 10> SVC SVC_RDRGETLOGONSERVER ret
; ; Mailslots YN ; ; Mailslots are always enabled with this redir, so return yes (TRUE, 1) ;
@@: dec bl jnz @f DbgPrintString <"NetGetEnumInfo: Mailslot check", 13, 10> mov ax,1 ret
; ; RIPL YN ; ; This redir doesn't know anything about RPL, so return no (FALSE, 0) ;
@@: dec bl jnz @f DbgPrintString <"NetGetEnumInfo: RIPL check", 13, 10> xor ax,ax ret
; ; RIPL UNC ;
@@: dec bl jnz @f DbgPrintString <"NetGetEnumInfo: return RIPL UNC", 13, 10> jmps DefaultServiceError
; ; RIPL drive ;
@@: dec bl jnz @f DbgPrintString <"NetGetEnumInfo: return RIPL drive", 13, 10> jmps DefaultServiceError
; ; Start marking CON_RIPL ;
@@: dec bl jnz @f DbgPrintString <"NetGetEnumInfo: Start marking CON_RIPL", 13, 10> jmps DefaultServiceError
; ; Stop marking CON_RIPL ;
@@: dec bl jnz @f DbgPrintString <"NetGetEnumInfo: Stop marking CON_RIPL", 13, 10> jmps DefaultServiceError
; ; exchange int 17 handlers ; ; We don't support this so return error ;
@@: dec bl jnz @f DbgPrintString <"NetGetEnumInfo: exchange int 17 handlers", 13, 10> jmps DefaultServiceError
; ; primary WrkNet ; ; This is transport-specific so we don't return anything except error ;
@@: dec bl jnz @f DbgPrintString <"NetGetEnumInfo: return primary WrkNet", 13, 10> jmps DefaultServiceError
; ; anything else - return an error ;
@@: DbgPrintString "NetGetEnumInfo: unknown request: " DbgPrintHexWord bx DbgCrLf jmps DefaultServiceError NetGetEnumInfo endp
page ; *** NetSpoolStuff ; * ; * Gets control from INT 2f/ax=1125h. This really has no use in NTVDM, ; * but we supply it because DOS has started making 1125 calls. Spooling ; * in NTVDM has nothing to do with the Redir TSR. Historically, printing ; * over the net was handled by the redir & this call was used (amongst ; * other things) to flush & close all spool files when an app terminated ; * ; * ENTRY AL = 7 Return truncate flag in DL (DH destroyed) ; * AL = 8 Set truncate flag from DL (must be 0 or 1) ; * AL = 9 Close all spool files ; * ; * EXIT CF = 1 ; * AX = ERROR_INVALID_FUNCTION ; * ; * USES ax, dx, si, ds, flags ; * ; * ASSUMES nothing ; * ; ***
PrintTruncate db 0
NetSpoolStuff proc near sub al,9 ; most common case first jnz @f
net_spool_stuff_good_exit: xor ax,ax ; nothing to do for CloseAllSpool! ret
@@: inc al jnz @f ; must be get, or invalid mov ax,ERROR_INVALID_PARAMETER cmp dl,1 ; must be 0 or 1 ja net_spool_stuff_error_exit mov PrintTruncate,dl jmp short net_spool_stuff_good_exit @@: inc al mov ax,ERROR_INVALID_FUNCTION jnz net_spool_stuff_error_exit
; ; return PrintTruncate flag to caller (app) ;
DosCallBack GET_USER_STACK mov dl,PrintTruncate xor dh,dh mov [si].User_Dx,dx ret
net_spool_stuff_error_exit: stc ret NetSpoolStuff endp
page if DEBUG even
public Old21Handler Old21Handler dd ?
public CheckInt21Function5e CheckInt21Function5e proc far assume cs:ResidentCode assume ds:nothing assume es:nothing assume ss:nothing
; cmp ah,5eh ; jnz @f ; DbgUnsupported @@: jmp Old21Handler ; let DOS handle it. DOS returns to caller CheckInt21Function5e endp endif
ResidentCodeEnd end
|