diff options
Diffstat (limited to '')
-rw-r--r-- | private/ntos/nbt/vxd/vnbtd.asm | 993 |
1 files changed, 993 insertions, 0 deletions
diff --git a/private/ntos/nbt/vxd/vnbtd.asm b/private/ntos/nbt/vxd/vnbtd.asm new file mode 100644 index 000000000..502f362f1 --- /dev/null +++ b/private/ntos/nbt/vxd/vnbtd.asm @@ -0,0 +1,993 @@ +;*****************************************************************; +;** Copyright(c) Microsoft Corp., 1988-1993 **; +;*****************************************************************; +;:ts=8 + TITLE VNBT - Netbios on TCP/IP vxd +.XLIST +;*** VNBT -- NetBios on TCP/IP VxD +; +; This module contains the device header for the NBT VxD driver. +; + .386p + include vmm.inc +ifdef CHICAGO + include ndis.inc +endif ;; CHICAGO + include dosmgr.inc + include netvxd.inc +IFDEF CHICAGO + include configmg.inc +ENDIF + include vwin32.inc + include vdhcp.inc + include debug.inc + include vtdi.inc + + Create_VNBT_Service_Table EQU True +ifdef CHICAGO + include vnbt.inc +else ;; CHICAGO + include vnbtd.inc +endif ;; CHICAGO + include vnetbios.inc + + include pageable.inc +.LIST + +Declare_Virtual_Device VNBT,3,0,VNBT_Control,VNBT_Device_ID, \ + VNBT_Init_Order,VNBT_Api_Handler,VNBT_Api_Handler + + +VxD_DATA_SEG +VxD_DATA_ENDS + +EXTRN __VxdMapSegmentOffsetToFlat:near ; from client.asm +ifndef CHICAGO +EXTRN _BSSBegin:DWORD +EXTRN _BSSDataEnd:DWORD +endif ;; CHICAGO +EXTRN _TdiDispatch:DWORD + +EXTRN _PostInit_Proc:NEAR +EXTRN _VxdApiWorker:NEAR + +ifndef CHICAGO +EXTRN _VNBT_NCB_X@20:NEAR +endif ;; CHICAGO + +EXTRN _GetDhcpOption:NEAR + + +VxD_ICODE_SEG + +EXTRN _Init:NEAR + +MSTCP db 'MSTCP',0 ; Protocol this driver sits on (this will have + ; to be changed to get it from an .ini file) +IFDEF CHICAGO +bInitialized db 0 ; 0 means not initialized, 1 means we've entered + ; the initialization, and 2 means we've left init +bSuccessInit db 0 ; 0 means initialization failed and all subsequent + ; initializations should fail +ENDIF + +NBTSectionName db 'NBT',0 ; Section where parameters are stored + +;**************************************************************************** +;** VNBT_Device_Init - VNBT device initialization service. +; +; The VNBT device initialization routine. Before calling anything +; we need to zero out the BSS data area. +; +; +; Entry: (EBX) - System VM Handle +; (EBP) - System Client Regs structure. +; +; Exit: 'CY' clear if we init. successfully. +; 'CY' set if we've failed. +; +BeginProc VNBT_Device_Init + +IFDEF CHICAGO + ; + ; Chicago calls us at both dynamic and static init, so only process + ; once + ; + cmp bInitialized, 2 ; 2 means we've already completed initialization + jne Init_Continue + clc ; Assume success (is checked below) + jmp Init_Exit + +Init_Continue: + mov bInitialized, 1 +ENDIF + +ifndef CHICAGO + mov edi, OFFSET32 _BSSBegin + mov ecx, OFFSET32 _BSSDataEnd + sub ecx, edi + shr ecx, 2 + sub eax, eax + cld + rep stosd +endif ;; CHICAGO + + VxDcall VTDI_Get_Version + jc Init_Exit ; Get out if VTDI is not installed + + ; + ; Get the TDI Vxd dispatch table for "MSTCP" to initialize the TDI + ; dispatch table (which will be needed by some of our + ; initialization stuff) + ; + mov eax, OFFSET32 MSTCP + push eax + VxDcall VTDI_Get_Info + add esp, 4 + cmp eax, 0 ; eax contains NULL or the pointer to the table + jne NoError + + Debug_Out "VNBT_Device_Init - VTDI_Get_Info failed!" + stc ; Set the carry + jmp Init_Exit + +NoError: + mov _TdiDispatch, eax + + ; + ; Initialize the rest of the driver + ; + call _Init + cmp eax, 1 ; Set 'CY' appropriately. + +Init_Exit: + +IFDEF CHICAGO + jc Exit2 ; Failed init, leave bSuccessInit 0 + + ; + ; If first time through and success, indicate successful initialization + ; + cmp bInitialized, 1 + je SetInitFlag + + ; + ; We've already been initialized once, was it successful? + ; + cmp bSuccessInit, 1 + clc ; test clears the carry so assume success + je Exit2 + + stc ; Set the carry since we failed init. last time + jmp Exit2 + +SetInitFlag: + clc + mov bSuccessInit, 1 + +Exit2: + mov bInitialized, 2 +ENDIF + ret + + + + +EndProc VNBT_Device_Init + + +VxD_ICODE_ENDS + +NBT_PAGEABLE_CODE_SEG + +ifdef CHICAGO +_NdisOpenProtocolConfiguration@12 PROC NEAR PUBLIC + VxDJmp NdisOpenProtocolConfiguration +_NdisOpenProtocolConfiguration@12 ENDP + +_NdisCloseConfiguration@4 PROC NEAR PUBLIC + VxDJmp NdisCloseConfiguration +_NdisCloseConfiguration@4 ENDP + +_NdisReadConfiguration@20 PROC NEAR PUBLIC + VxDJmp NdisReadConfiguration +_NdisReadConfiguration@20 ENDP +endif ;; CHICAGO + +NBT_PAGEABLE_CODE_ENDS + +VxD_CODE_SEG +;**************************************************************************** +;* NCB_Handler +; +; Called by VNetBios when NCBs need to be submitted to this driver +; +; ENTRY: +; EBX = NCB being submitted +; +; EXIT: +; AL - return code +; +BeginProc NCB_Handler + + ; + ; In the master portion of the mif tests, after hitting ctrl-c during + ; the attempt to synchronize, a wait add group name NCB is + ; submitted with interrupts disabled. The CTE timer event handler + ; checks this and schedules an event for when they are re-enabled, + ; however since it's a wait NCB, we deadlock in VNBT_NCB_X's block. + ; + ; Make sure interrupts are enabled. + ; BUGBUG - Why were we called with ints disabled? + ; + ;VMMcall Enable_VM_Ints + + xor eax, eax ; second parm of VNBT_NCB_X is unused when + +ifndef CHICAGO + + push eax + push eax + push eax ; called from here, but is used (e.g.nbtstat) + push eax + push ebx + call _VNBT_NCB_X@20 ; when VNBT_NCB_X is called directly + +else ;; CHICAGO +if 0 +; +; As of 08-Feb-1996 there is a bug in "vmm.h" where this doesn't +; work properly, with the result being a misaligned stack pointer. +; + VxDCall VNBT_NCB_X, <ebx, eax, eax, eax, eax> +else ;; 0 + push eax + push eax + push eax + push eax + push ebx + VxDCall VNBT_NCB_X +endif ;; 0 +endif ;; CHICAGO + + ret +EndProc NCB_Handler + +;**************************************************************************** +;** _DhcpQueryOption - Queries a DHCP option +; +; Stub callout to the Dhcp driver +; +; Entry: [ESP+4] - IP Address of interest +; [ESP+8] - DHCP Option number +; [ESP+12]- Pointer to buffer +; [ESP+16]- Pointer to buffer size +; +; + +BeginProc _DhcpQueryOption + + VxdCall VDHCP_Get_Version + jnc DQI_Installed + + mov eax, 26 ; DHCP not installed, return invalid param + ret + +DQI_Installed: + push ebp + mov ebp,esp + + mov eax, [ebp+20] ; Buff size + push eax + mov eax, [ebp+16] ; Buff + push eax + mov eax, [ebp+12] ; Option + push eax + mov eax, [ebp+8] ; IP Address + push eax + + VxdCall VDHCP_Query_Option + + add esp, 16 + + pop ebp + ret + +EndProc _DhcpQueryOption + +;**************************************************************************** +;** VNBT_Get_Version - VNBT get version service +; +; Called by using devices to make sure the VNBT driver +; is present. Also returns the version of the VNBT driver. +; +; Entry: Nothing +; +; Exit: On success, 'CY' is clear, and +; AH - Major version # of driver. +; AL - Minor version # +; +; On failure, 'CY' is set. +; +; Uses: AX +; +BeginProc VNBT_Get_Version, SERVICE + + mov ax, VNBT_VERSION + clc + ret + +EndProc VNBT_Get_Version + +VxD_CODE_ENDS +NBT_PAGEABLE_CODE_SEG + +;**************************************************************************** +;** VNBT_Device_PostProc - do postprocessing +; +; Called by the sytem when all the other stuff (in our case, rdr) is +; loaded. At this we read the lmhosts file, so that any #INCLUDE with +; UNC names in it will work. +; This routine can also be used for other stuff, but for now only lmhosts +; stuff. +; +BeginProc VNBT_Device_PostProc + + call _PostInit_Proc + clc + ret + +EndProc VNBT_Device_PostProc + +NBT_PAGEABLE_CODE_ENDS +VxD_CODE_SEG + +;**************************************************************************** +;** VNBT_Control - VNBT device control procedure +; +; This procedure dispatches VxD messages to the appropriate handler. +; +; Entry: EBX - VM handle +; (EBP) - Client reg structure +; +; Exit: 'NC' is success, 'CY' on failure +; +; Uses: All +; +BeginProc VNBT_Control + + Control_Dispatch Device_Init, VNBT_Device_Init + Control_Dispatch Sys_Dynamic_Device_Init, VNBT_Device_Init + Control_Dispatch Sys_Vm_Init, VNBT_Device_PostProc +IFDEF CHICAGO + Control_Dispatch W32_DEVICEIOCONTROL, VNBT_DeviceIoControl +ENDIF + + clc + ret + +EndProc VNBT_Control + +IFDEF CHICAGO +;******************************************************************* +;** VNBT_DeviceIoControl +; +; Dispatch routine for VxD services invoked via the Win32 +; DeviceIoControl API. +; +; Entry: (ESI) - Points to DIOCParams structure (see VWIN32.H). +; +; Exit: (EAX) - Win32 status code, -1 for asynchronous +; completion. +; HISTORY: +; Koti 10-Nov-1994 Created (Modified from wsock version) +; +;******************************************************************** +BeginProc VNBT_DeviceIoControl + +;;; +;;; Setup stack frame. +;;; + + push ebx + push esi + push edi + + mov eax, [esi.dwIoControlCode] + cmp ecx, DIOC_GETVERSION + je vdic_doNothing + cmp ecx, DIOC_CLOSEHANDLE + jne vdic_doSomething + +;;; +;;; For devioctl calls resulting from CreateFile and CloseFile, we don't do +;;; anything other than return success. +;;; + +vdic_doNothing: + xor eax, eax + jmp vdic_CommonExit + +;;; +;;; This is an ioctl requiring some work: call our api worker (VxdApiWorker) +;;; + +vdic_doSomething: + +;;; Lock the in-buffer. + + mov eax, [esi.lpvInBuffer] + or eax, eax + jz vdic_outbuf + + cCall __VxdLockBuffer, <eax, [esi.cbInBuffer]> + or eax, eax + jz vdic_LockFailure + mov [esi.lpvInBuffer], eax + +vdic_outbuf: + +;;; Lock the out-buffer. + + mov eax, [esi.lpvOutBuffer] + or eax, eax + jz vdic_callApi + + cCall __VxdLockBuffer, <eax, [esi.cbOutBuffer]> + or eax, eax + jz vdic_LockFailure + mov [esi.lpvOutBuffer], eax + +vdic_callApi: + + mov eax, 0 ; VxdApiWorker won't trash input buffer + push eax + mov eax, [esi.cbInBuffer] + push eax + mov eax, [esi.lpvInBuffer] + push eax + mov eax, [esi.cbOutBuffer] + push eax + mov eax, [esi.lpvOutBuffer] + push eax + mov eax, [esi.dwIoControlCode] + push eax + + call _VxdApiWorker + add esp, 24 + + +;;; Unlock the in-buffer. + + push eax ; save the return code from VxdApiWorker + cCall __VxdUnlockBuffer, <[esi.lpvInBuffer], [esi.cbInBuffer]> + pop eax + +;;; Unlock the out-buffer. + + push eax ; save the return code from VxdApiWorker + cCall __VxdUnlockBuffer, <[esi.lpvOutBuffer], [esi.cbOutBuffer]> + pop eax + +vdic_CommonExit: + + pop edi + pop esi + pop ebx + + ret + +;;; +;;; Failed to lock parameter structure. +;;; + +vdic_LockFailure: + + Debug_Out "VNBT_DeviceIoControl: cannot lock parameters" + + mov eax, 1784 ; ERROR_INVALID_USER_BUFFER + jmp vdic_CommonExit + +EndProc VNBT_DeviceIoControl + +;******************************************************************* +;** _ReconfigureDevnode +; +; This routine schedules an AppyTime call for the ConfigMgr to +; call us back when it's ready. It calls our routine VNBT_ConfigCalls +; +; Entry: ESP+4 our devnode on the stack +; +; Exit: (EAX) - 0 if everything goes well +; 1 if something goes wrong +; +; HISTORY: +; Koti 15-Dec-1994 Created +; +;******************************************************************** + +BeginProc _ReconfigureDevnode + + push ebp + mov ebp, esp + + xor eax, eax + push eax ; the flags + mov eax, [ebp+8] ; our devnode + push eax ; this is our RefData + lea eax, VNBT_ConfigCalls ; call back routine + push eax + VxdCall _CONFIGMG_Call_At_Appy_Time + add esp, 12 + cmp eax, CR_SUCCESS + je ReconfigureDevnode_PASS + mov eax, 1 + jmp ReconfigureDevnode_Exit + +ReconfigureDevnode_PASS: + xor eax, eax + +ReconfigureDevnode_Exit: +IFDEF DBG + or eax, eax + jz ReconfigureDevnode_GoodJob + int 3 +ReconfigureDevnode_GoodJob: +ENDIF + pop ebp + ret +EndProc _ReconfigureDevnode + +VxD_CODE_ENDS + +NBT_PAGEABLE_CODE_SEG + +;******************************************************************* +;** VNBT_ConfigCalls +; +; This routine makes all the calls to the Config Mgr so that our +; devnode is reconfigured. We first get vredir's devnode, kill it +; and then reenumerate all the children again. This way vredir +; gets the msg from ConfigMgr to do whatever it does with a new devnode. +; +; If dhcp lease expires and then comes back in, vredir had no way +; of knowing that lana is usable again: hence this convoluted way. +; +; IMPORTANT: if chicago ever changes to add more children to tcp's +; devnode, this function needs to be modified to enumerate +; rest of the children and kill them! +; +; Entry: (EDX) - our devnode +; +; Exit: (EAX) - 0 if everything goes well +; 1 if something goes wrong +; +; HISTORY: +; Koti 15-Dec-1994 Created +; +;******************************************************************** + +VnbtScratch dd 0 + +BeginProc VNBT_ConfigCalls + + push ebp + mov ebp, esp + push esi + push edi + push ecx + + ;;; First get the first child + xor eax, eax + push eax ; the flags + mov eax, [ebp+8] + push eax ; our devnode + lea eax, VnbtScratch ; this is where we will receive child node + push eax + VxdCall _CONFIGMG_Get_Child + add esp, 12 + mov esi, dword ptr [VnbtScratch] ;save the first child in esi + mov edi, 0 ; for now, make esi,edi different + cmp eax, CR_SUCCESS + je ConfigCalls_Label2 + mov ecx, 1 + jmp ConfigCalls_Exit + + ;;; Get a sibling of this child +ConfigCalls_Label2: + cmp edi, esi ; did we just kill the first child + je ConfigCalls_Label6 ; yes: we are done with all the killings + xor eax, eax + push eax ; the flags + push esi ; the first child + lea eax, VnbtScratch ; this is where we will receive sibling + push eax + VxdCall _CONFIGMG_Get_Sibling + add esp, 12 + mov edi, dword ptr [VnbtScratch] ;edi contains sibling + cmp eax, CR_SUCCESS ; found a sibling? + je ConfigCalls_Label4 ; yes, go kill it + cmp eax, CR_NO_SUCH_DEVNODE ; done with all siblings? + je ConfigCalls_Label3 ; yes, go kill the first child + mov ecx, 2 ; hmmm: something went wrong + jmp ConfigCalls_Exit + + ;;; Done with all the siblings: now kill the first child +ConfigCalls_Label3: + mov edi, esi ; esi=first child, edi=child to kill + +ConfigCalls_Label4: + ;;; Now, ask ConfigMgr if it's ok to kill our child + xor eax, eax + push eax ; the flags + push edi ; sibling's devnode + VxdCall _CONFIGMG_Query_Remove_SubTree + add esp, 8 + cmp eax, CR_SUCCESS ; ok to kill? + je ConfigCalls_Label5 ; nope! + mov ecx, 4 + jmp ConfigCalls_Exit + +ConfigCalls_Label5: + ;;; Now that ConfigMgr approved, kill the child + xor eax, eax + push eax ; the flags + push edi ; sibling's devnode + VxdCall _CONFIGMG_Remove_SubTree + add esp, 8 + cmp eax, CR_SUCCESS ; did it die? + je ConfigCalls_Label2 ; yes, it did: go kill other siblings + mov ecx, 5 ; nope! + jmp ConfigCalls_Exit + +ConfigCalls_Label6: + ;;; Ok, reenumerate our devnode so our children come back to life + xor eax, eax + push eax ; the flags + mov eax, [ebp+8] + push eax ; our devnode + VxdCall _CONFIGMG_Reenumerate_DevNode + add esp, 8 + cmp eax, CR_SUCCESS ; did it die? + je ConfigCalls_Label7 ; nope! + mov ecx, 6 + jmp ConfigCalls_Exit + +ConfigCalls_Label7: + xor eax, eax + +ConfigCalls_Exit: +IFDEF DBG + or eax, eax + jz ConfigCalls_GoodJob + int 3 +ConfigCalls_GoodJob: +ENDIF + pop ecx + pop edi + pop esi + pop ebp + ret +EndProc VNBT_ConfigCalls + +ENDIF + +NBT_PAGEABLE_CODE_ENDS + +VxD_CODE_SEG + +;**************************************************************************** +;** _GetInDosFlag - Retrieves the InDos flag +; +; +; Note: This routine cannot be called at init time (vdosmgr complains +; the variable not initialized yet) +; +; Returns the flag in ax +; + +BeginProc _GetInDosFlag + + push ebx + + VxdCall DOSMGR_Get_IndosPtr + + ; + ; Add CB_High_Linear if we are in V86 mode + ; + + VMMcall Get_Cur_VM_Handle + + test [ebx.CB_VM_Status], VMStat_PM_Exec + jnz GIF_Exit + + add eax, [ebx.CB_High_Linear] + +GIF_Exit: + movzx eax, word ptr [eax] + + pop ebx + ret +EndProc _GetInDosFlag + +;**************************************************************************** +; +; ULONG +; RtlCompareMemory ( +; IN PVOID Source1, +; IN PVOID Source2, +; IN ULONG Length +; ) +; +; Routine Description: +; +; This function compares two blocks of memory and returns the number +; of bytes that compared equal. +; +; Arguments: +; +; Source1 (ebp+8) - Supplies a pointer to the first block of memory to +; compare. +; +; Source2 (ebp+12) - Supplies a pointer to the second block of memory to +; compare. +; +; Length (ebp+16) - Supplies the Length, in bytes, of the memory to be +; compared. +; +; Return Value: +; +; The number of bytes that compared equal is returned as the function +; value. If all bytes compared equal, then the length of the orginal +; block of memory is returned. +; +;-- + +RcmSource1 equ [ebp+8] +RcmSource2 equ [ebp+12] +RcmLength equ [ebp+16] + +public _VxdRtlCompareMemory +BeginProc _VxdRtlCompareMemory + + push ebp + mov ebp,esp + push esi + push edi + cld + + mov esi,RcmSource1 ; (esi) -> first block to compare + mov edi,RcmSource2 ; (edi) -> second block to compare + mov ecx,RcmLength ; (ecx) = length in bytes + and ecx,3 ; (ecx) = length mod 4 + jz rcm10 ; 0 odd bytes, go do dwords + +; +; Compare "odd" bytes. +; + + repe cmpsb ; compare odd bytes + jnz rcm40 ; mismatch, go report how far we got + +; +; Compare dwords. +; + +rcm10: mov ecx,RcmLength ; (ecx) = length in bytes + shr ecx,2 ; (ecx) = length in dwords + jz rcm20 ; no dwords, go exit + + repe cmpsd ; compare dwords + jnz rcm30 ; mismatch, go find byte + +; +; When we come to rcm20, we matched all the way to the end. Esi +; points to the byte after the last byte in the block, so Esi - RcmSource1 +; equals the number of bytes that matched +; + +rcm20: sub esi,RcmSource1 + mov eax,esi + pop edi + pop esi + pop ebp + ret + +; +; When we come to rcm30, esi (and edi) points to the dword after the +; one which caused the mismatch. Back up 1 dword and find the byte. +; Since we know the dword didn't match, we can assume one byte won't. +; + +rcm30: sub esi,4 ; back up + sub edi,4 ; back up + mov ecx,5 ; ensure that ecx doesn't count out + repe cmpsb ; find mismatch byte + +; +; When we come to rcm40, esi points to the byte after the one that +; did not match, which is TWO after the last byte that did match. +; + +rcm40: dec esi + sub esi,RcmSource1 + mov eax,esi + pop edi + pop esi + pop ebp + ret + +EndProc _VxdRtlCompareMemory + +;**************************************************************************** +;** VNBT_Api_Handler - handles all request from other vxd's, v86-mode apps +; +; This procedure does all the address translations, memory locking etc. +; and calls the C routine VxdApiWorker() to do the actual work +; +; Entry: EBX - VM handle +; (EBP) - Client reg structure +; +; Exit: 'NC' is success, 'CY' on failure +; +; Uses: All +; +; HISTORY: +; Koti 16-Jun-1994 Created (Modified from dhcp's version) +; +;******************************************************************** +BeginProc VNBT_Api_Handler + + + push ebp + push ebx + push esi + push edi + push edx + push ecx + +;;; get function op code + + movzx edi, [ebp.Client_CX] + +;;; +;;; Convert the parameter buffer pointers from segmented to flat. +;;; + +;;; first, the output buffer + + movzx eax, [ebp.Client_BX] + push eax + movzx eax, [ebp.Client_ES] + push eax + push ebx + call __VxdMapSegmentOffsetToFlat + add esp, 12 + + cmp eax, 0FFFFFFFFh + je vnbt_Fault + +;;; +;;; Lock the output buffer. +;;; + + or eax, eax + jz vnbt_DontLock_OutBuf + + movzx ecx, [ebp.Client_DI] + cCall __VxdLockBuffer, <eax, ecx> + + or eax, eax + jz vnbt_Fault + +vnbt_DontLock_OutBuf: + + mov esi, eax + +;;; now, convert and lock the input buffer + + movzx eax, [ebp.Client_AX] + push eax + movzx eax, [ebp.Client_DX] + push eax + push ebx + call __VxdMapSegmentOffsetToFlat + add esp, 12 + + cmp eax, 0FFFFFFFFh + je vnbt_Fault + + or eax, eax + jz vnbt_DontLock + + movzx ebx, [ebp.Client_SI] + cCall __VxdLockBuffer, <eax, ebx> ; this preserves esi + + or eax, eax + jz vnbt_Fault + +vnbt_DontLock: + + mov edx, eax + +;;; call worker routine +;;; edi - opcode +;;; esi - OutBuffer pointer +;;; ecx - OutBuffer length +;;; edx - InBuffer pointer +;;; ebx - InBuffer length + +; +; RLF 05/30/94 - __VxdLockBuffer destroys contents of cx - reload +; + + push esi ; save OutBuffer addr + push edx ; save InBuffer addr + + mov eax, 1 ; VxdApiWorker will trash input buffer + push eax + movzx ecx, [ebp.Client_DI] + movzx ebx, [ebp.Client_SI] + push ebx + push edx + push ecx + push esi + push edi + + call _VxdApiWorker + add esp, 24 + + pop edx ; restore InBuffer addr + pop esi ; restore OutBuffer addr + + mov [ebp.Client_AX], ax + +;;; +;;; Unlock the parameter buffer. +;;; + + or esi, esi + jz vnbt_DontUnLock_OutBuf + + push edx ; save InBuffer addr + movzx ecx, [ebp.Client_DI] + cCall __VxdUnlockBuffer <esi, ecx> + pop edx ; restore InBuffer addr +vnbt_DontUnLock_OutBuf: + + or edx, edx + jz vnbt_DontUnLock + + movzx ebx, [ebp.Client_SI] + cCall __VxdUnlockBuffer <edx, ebx> + +vnbt_DontUnLock: + +vnbt_CommonExit: + +;;; Restore stack fame + pop ecx + pop edx + pop edi + pop esi + pop ebx + pop ebp + ret + +;;; +;;; Either failed to map a segmented pointer to flat or failed +;;; to lock the parameter buffer. +;;; + +vnbt_Fault: + + cmp eax, 0FFFFFFFFh + mov [ebp.Client_AX], ax + jmp vnbt_CommonExit + + +EndProc VNBT_Api_Handler + +VxD_CODE_ENDS +END + |