The Wayback Machine - https://web.archive.org/web/20141025202805/http://www.coderbliss.com/2014/10/24/windows-7-netbios-library-in-visual-basic/
Oct 242014
 

Had an application that communicated with test controller PC via Ethernet using NetBIOS. Basically, the test controller acted like a NetBIOS server waiting for connections and subsequent commands.

Below is the entire NetBIOS library.  NOTE: In Windows 7 64-bit, found that compile w/ CPU as ANY resulted in runtime errors to the underlying Windows NetBios API.  However, compiling with CPU as x86 worked fine.

 

Imports System.Runtime.InteropServices

' FILE HEADER ----------------------------------------------
' FILE     : NETBIOS.BAS
' COPYRIGHT: 2000 to 2014 Reedholm Instruments Co.
' AUTHOR(s): Jon Reedholm
' VERSION  : 1.05
' DATE     : 5/23/2014
'-----------------------------------------------------------

' REVISION HISTORY------------------------------------------
'  1.00 JSR 8/03/2000 SPR 2/1/2000-01
'       Created.
'...........................................................
'  1.01 JSR 9/26/2000 SPR 2/1/2000-01
'       Modified to have public types & constants object
'       class compatible.
'...........................................................
'  1.02 JSR 4/03/2001 SPR 2/1/2000-01
'       Made into ActiveX DLL.  Added notes mainly.
'..........................................................  
'  1.03 JSR 4/11/2012 ECR 01/25/2011-1
'       Started conversion for Windows 2.00
'...........................................................
'  1.04 JSR 6/25/2012
'       Added NB_AdapterStat, netLoopUntilReady and modified
'       NB_SessionStat during debugging of network issue
'       with new server.  Changes not used, but left in
'       in case needed in future.
'..........................................................  
'  1.05 JSR 5/23/2014 ECR 01/25/2011-1
'       Got working with Win7 64bit. 
'-----------------------------------------------------------

' REFERENCES -----------------------------------------------
'  IBM NetBIOS Application Development Guide
'
'  MSDN library on NetBIOS call, structures, & constants -
'  of which a copy has been placed in the Web Project Notes
'-----------------------------------------------------------

' NOTES ----------------------------------------------------
'  Low level NetBIOS subroutines used to communicate with
'  the slave PC.  These routines use the Windows
'  NET32API.DLL for the actual NetBIOS call.  Most of the
'  following constants and structures were provided from
'  the API viewer.  However, the structures were incorrect
'  by assigning a C syntax UCHAR as an integer, instead of
'  a byte.
'
'  Visual Basic moves variables in memory, thus extra care
'  needs to be used when passing a buffer pointer to
'  a API routine--such as NetBIOS.  This is especially true
'  for an array variable.  To do this, marshalling and 
'  using unmanaged data types was required in VB 2010.
'
'...........................................................
'  Have learned that NetBIOS appears to not look beyond first
'  eight characters to see if NetBIOS names added to NetBIOS
'  table are the same.  Didn't look into this further, since
'  ActiveX DLL only using one connection at a time.
'
'...........................................................
'  Got it to work by the following:
'   Making sure every item in NCB structure had Marshal setting.
'   Compiled DLLs and EXEs with X86 CPU.
'   Used Ctype for returning LANAS.
'
' Trick was making sure to have MarshalAs on every item in 
' NCB structure and then switching to X86 for platform, 
' since NETAPI32.DLL is 32-bit. 
'
'  Per Microsoft, NetBIOS is no longer supported after Win XP.  
'  They suggest using other comm. method  such as named pipes.  
'-----------------------------------------------------------
Public Module NetBios
  '-----------------------------------------------------------
  ' Below constants are all used NetBIOS commands. More
  ' commands than those listed exist, but are not used.
  '-----------------------------------------------------------
  Private Const NCBNOWAIT As Byte = &H80                 '[Sets command to not wait]
  Private Const NCBACTION As Byte = &H77
  Private Const NCBADDNAME As Byte = &H30
  Private Const NCBASTAT As Byte = &H33
  Private Const NCBCALL As Byte = &H10
  Private Const NCBCANCEL As Byte = &H35
  Private Const NCBDELNAME As Byte = &H31
  Private Const NCBENUM As Byte = &H37
  Private Const NCBHANGUP As Byte = &H12
  Private Const NCBLANSTALERT As Byte = &H73
  Private Const NCBLISTEN As Byte = &H11
  Private Const NCBRECV As Byte = &H15
  Private Const NCBRESET As Byte = &H32
  Private Const NCBSEND As Byte = &H14
  Private Const NCBSSTAT As Byte = &H34

  '-----------------------------------------------------------
  ' Below constants are used with NCB commands
  '-----------------------------------------------------------
  Private Const ncbRcvTimeOut As Byte = 10      '[Set recv cmds timeout 5s]

  Private Const ncbSndTimeOut As Byte = 60     '[Set send cmds timeout 30s]

  '-----------------------------------------------------------
  ' The Lana_ENUM structure is used to store all the network
  ' adapter LAN #s found on the PC--used for NetBIOS calls
  '-----------------------------------------------------------
  Public Enum LANAenum
    maxLANA = 254
  End Enum

  '-----------------------------------------------------------
  ' Below are all the possible NetBIOS errors
  '-----------------------------------------------------------
  Public Enum netbErrors As Byte
    nrcACTSES = &HF
    nrcBADDR = &H7
    nrcBRIDGE = &H23
    nrcLEN = &H1
    nrcCANCEL = &H26
    nrcCANOCCR = &H24
    nrcCMDCAN = &HB
    nrcCMDTMO = &H5
    nrcDUPENV = &H30
    nrcDUPNAME = &HD
    nrcENVNOTDEF = &H34
    nrcGOODRET = &H0
    nrcIFBUSY = &H21
    nrcILLCMD = &H3
    nrcILLNN = &H13
    nrcINCOMP = &H6
    nrcINUSE = &H16
    nrcINVADDRESS = &H39
    nrcINVDDID = &H3B
    nrcLOCKFAIL = &H3C
    nrcLOCTFUL = &H11
    nrcMAXAPPS = &H36
    nrcNAMCONF = &H19
    nrcNAMERR = &H17
    nrcNAMTFUL = &HE
    nrcNOCALL = &H14
    nrcNORES = &H9
    nrcNORESOURCES = &H38
    nrcNOSAPS = &H37
    nrcNOWILD = &H15
    nrcOPENERR = &H3F
    nrcOSRESNOTAV = &H35
    nrcPENDING = &HFF
    nrcREMTFUL = &H12
    nrcSABORT = &H18
    nrcSCLOSED = &HA
    nrcSNUMOUT = &H8
    nrcSYSTEM = &H40
    nrcTOOMANY = &H22
  End Enum

  '-----------------------------------------------------------
  ' NetBIOS Network Control Block structure--which is used to
  ' issue all commands to the NetBIOS protocol
  '-----------------------------------------------------------
  Public Enum netbstrcs
    netNameLen = 16                              '[Length if name in bytes]
    netresvLen = 11                              '[Length of reserve array]
    netbuffer = 32000                          '[Total size of data butter]
    netnumSess = 10                      '[Total number of active sessions]
    netMAC = 7                                           '[MAC address len]
    netnumNames = 17            '[Number of netbios names in adapter table]
  End Enum

  '-----------------------------------------------------------
  '  Used IntPtr, but have to compile EXE (or atleast RICLIENT>DLL)
  '  as x86 platform for call to NetAPI32.DLL to work - 
  '  otherwise get exception error inside NetBios call.
  '-----------------------------------------------------------
  <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)> _
  Public Structure NCB
    <MarshalAs(UnmanagedType.U1)> _
    Public ncbCommand As Byte
    <MarshalAs(UnmanagedType.U1)> _
    Public ncbRetcode As Byte
    <MarshalAs(UnmanagedType.U1)> _
    Public ncbLSN As Byte
    <MarshalAs(UnmanagedType.U1)> _
    Public ncbNum As Byte
    <MarshalAs(UnmanagedType.SysUInt)> _
    Public ncbBuffer As IntPtr
    <MarshalAs(UnmanagedType.U2)> _
    Public ncbLength As Int16
    <MarshalAs(UnmanagedType.ByValArray, ArraySubType:=UnmanagedType.U1, _
               SizeConst:=netbstrcs.netNameLen)> Dim ncbCallname() As Byte
    <MarshalAs(UnmanagedType.ByValArray, ArraySubType:=UnmanagedType.U1, _
               SizeConst:=netbstrcs.netNameLen)> Dim ncbName() As Byte
    <MarshalAs(UnmanagedType.U1)> _
    Public ncbRTO As Byte
    <MarshalAs(UnmanagedType.U1)> _
    Public ncbSTO As Byte
    <MarshalAs(UnmanagedType.U4)> _
    Public ncbPost As UInt32 'IntPtr
    <MarshalAs(UnmanagedType.U1)> _
    Public ncbLANAnum As Byte
    <MarshalAs(UnmanagedType.U1)> _
    Public ncbCmdCplt As Byte
    <MarshalAs(UnmanagedType.ByValArray, ArraySubType:=UnmanagedType.U1, _
               SizeConst:=netbstrcs.netresvLen)> Dim ncbReserve() As Byte
    <MarshalAs(UnmanagedType.U4)> _
    Public ncbEvent As Int32 'IntPtr
  End Structure

  <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi)> _
  Public Structure LANA_ENUM
    <MarshalAs(UnmanagedType.U1)> _
    Public Length As Byte
    <MarshalAs(UnmanagedType.ByValArray, SizeConst:=LANAenum.maxLANA + 1)> Dim LANA() As Byte
  End Structure

  '-----------------------------------------------------------
  ' The SessionHeader and SessionBUFFER structures are used
  ' to get the status of an active NetBIOS session
  '-----------------------------------------------------------
  <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi)> _
  Private Structure SessionBuffer
    Public LSN As Byte
    Public State As Byte
    <MarshalAs(UnmanagedType.ByValArray, ArraySubType:=UnmanagedType.U1, _
               SizeConst:=netbstrcs.netNameLen)> Dim LocalName() As Byte
    <MarshalAs(UnmanagedType.ByValArray, ArraySubType:=UnmanagedType.U1, _
               SizeConst:=netbstrcs.netNameLen)> Dim RemoteName() As Byte
    Public ReceivesOutstanding As Byte
    Public SendsOutstanding As Byte
  End Structure

  <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi)> _
  Private Structure SessionHeader
    Public SessName As Byte
    Public NumSess As Byte
    Public RcvDgOutstanding As Byte
    Public RcvAnyOutstanding As Byte
    <MarshalAs(UnmanagedType.ByValArray, SizeConst:=netbstrcs.netnumSess)> Dim LocStatData() As SessionBuffer
  End Structure

  '-----------------------------------------------------------
  ' Adapter Status Buffer
  '-----------------------------------------------------------
  <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi)> _
  Private Structure Name_Buffer
    <MarshalAs(UnmanagedType.ByValArray, ArraySubType:=UnmanagedType.U1, _
               SizeConst:=netbstrcs.netNameLen)> Dim LocalName() As Byte
    Public name_num As Byte
    Public name_flags As Byte
  End Structure

  <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi)> _
  Private Structure Adapter_Status
    <MarshalAs(UnmanagedType.ByValArray, ArraySubType:=UnmanagedType.U1, _
               SizeConst:=netbstrcs.netMAC)> Dim adapter_address() As Byte
    Public rev_major As Byte
    Public reserved0 As Byte
    Public adapter_type As Byte
    Public rev_minor As Byte
    Public duration As Int16
    Public frmr_recv As Int16
    Public frmr_xmit As Int16
    Public iframe_recv_err As Int16
    Public xmit_aborts As Int16
    Public xmit_success As Int32
    Public recv_success As Int32
    Public iframe_xmit_err As Int16
    Public recv_buff_unavail As Int16
    Public t1_timeouts As Int16
    Public ti_timeouts As Int16
    Public reserved1 As Int32
    Public free_ncbs As Int16
    Public max_cfg_ncbs As Int16
    Public max_ncbs As Int16
    Public xmit_buf_unavail As Int16
    Public max_dgram_size As Int16
    Public pending_sess As Int16
    Public max_cfg_sess As Int16
    Public max_sess As Int16
    Public max_sess_pkt_size As Int16
    Public name_count As Int16
    <MarshalAs(UnmanagedType.ByValArray, SizeConst:=netbstrcs.netnumNames)> Dim NameTable() As Name_Buffer
  End Structure

  '-----------------------------------------------------------
  ' Used to store data being Sent/Receive from NetBIOS call
  '-----------------------------------------------------------
  '<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi)> _
  Private Structure DataBuffer
    <MarshalAs(UnmanagedType.ByValArray, SizeConst:=32000)> Dim ncbBufStat() As Byte
  End Structure

  '-----------------------------------------------------------
  'Reference to NetBIOS function in Windows Network API DLL
  '-----------------------------------------------------------
  Private Declare Ansi Function NetBios Lib "netapi32.dll" _
     Alias "Netbios" (ByRef pncb As NCB) As Byte
  Private Declare Ansi Function NetApiBufferAllocate Lib "netapi32.dll" _
     Alias "NetApiBufferAllocate" (ByVal bytecount As Long, ByRef buffer As ULong) As Long
  Private Declare Ansi Function NetApiBufferFree Lib "netapi32.dll" _
     Alias "NetApiBufferFree" (ByRef buffer As ULong) As Long
  '-----------------------------------------------------------
  ' End declarations
  '-----------------------------------------------------------

  '-----------------------------------------------------------
  ' VERSION: 1.02
  ' DATE   : 4/11/2012
  '...........................................................
  ' DEFINITION/NOTES:
  '  Used to init an NCB structure.
  '-----------------------------------------------------------
  Public Sub InitNCB(ByRef pncb As NCB)
    With pncb
      .ncbCommand = 0
      .ncbRetcode = 0
      .ncbLSN = 0
      .ncbNum = 0
      .ncbBuffer = 0
      .ncbLength = 0
      
      ReDim .ncbCallname(netbstrcs.netNameLen - 1)
      ReDim .ncbName(netbstrcs.netNameLen - 1)
      .ncbRTO = 0
      .ncbSTO = 0
      .ncbPost = 0
      .ncbLANAnum = 0
      .ncbCmdCplt = 0
      ReDim .ncbReserve(netbstrcs.netresvLen - 1)
      .ncbEvent = 0
    End With
  End Sub

  '-----------------------------------------------------------
  ' VERSION: 1.02
  ' DATE   : 4/11/2012
  '...........................................................
  ' DEFINITION/NOTES:
  '  Initializes the LANAS array.
  '-----------------------------------------------------------
  Public Sub InitLANA_ENUM(ByRef LANAS As LANA_ENUM)

    Dim Cnt As Int16

    'STARTS ----------------------------------------------------
    LANAS.Length = 0
    ReDim LANAS.LANA(LANAenum.maxLANA)
    For Cnt = 0 To LANAenum.maxLANA
      LANAS.LANA(Cnt) = 0
    Next
  End Sub

  '-----------------------------------------------------------
  ' VERSION: 1.02
  ' DATE   : 4/11/2012
  '...........................................................
  ' DEFINITION/NOTES:
  '  Converts a VB string into a char array for the netbios
  '  calls.  Uses a varient type on purpose that it assumes is
  '  an array of bytes starting at 0.
  '-----------------------------------------------------------
  Public Sub NB_PutString(ByVal InString As String, _
                          ByVal MoveBytes As Int16, _
                          ByRef OutString As Object)

    Dim Cnt As Integer                              '[Counter for the array]
    Dim wStr As String                        '[Temp string to store 1 char]

    'STARTS ----------------------------------------------------
    While Len(InString) < MoveBytes                 '[Add spaces to end +1]
      InString = InString & Chr(32)
    End While
    If TypeOf (OutString) Is String Then
      OutString = ""
    End If

    For Cnt = 1 To Len(InString)                   '[ Move into 0 pos array]
      wStr = Left(InString, 1)
      InString = Right(InString, Len(InString) - 1)

      'OutString(Cnt - 1) = wStr
      If TypeOf (OutString) Is String Then
        OutString = ""
      Else
        OutString(Cnt - 1) = Asc(wStr)
      End If
    Next Cnt
  End Sub

  '-----------------------------------------------------------
  ' VERSION: 1.02
  ' DATE   : 4/11/2012
  '...........................................................
  ' DEFINITION/NOTES:
  '  Converts a char array into a VB string.
  '  Uses a varient type on purpose that it assumes is an
  '  array of bytes starting at 0.
  '-----------------------------------------------------------
  Public Sub NB_GetString(ByRef InString As Object, _
                          ByVal MoveBytes As Int16, _
                          ByRef OutString As String)

    Dim Cnt As Int16                              '[Counter for the array]

    'STARTS -----------------------------------------------------
    OutString = ""
    For Cnt = 0 To MoveBytes - 1
      OutString = OutString & Chr(InString(Cnt))
    Next Cnt
  End Sub
  '-----------------------------------------------------------
  ' VERSION: 1.02
  ' DATE   : 4/12/2012
  '...........................................................
  ' DEFINITION/NOTES:
  '  Generates a list of the adapter/protocol numbers (lanas).
  '  This list is stored in public and should only have to
  '  be issued once when starting program.  However, with
  '  Windows plug-n-play it is possible that the network
  '  configuration will change without a reboot.
  '
  '  Used in conjunction with NB_Listen or NB_Call to make a
  '  slave PC connection.
  '-----------------------------------------------------------
  Public Function callNetBios(ByRef wNCB As NCB) As Byte

    Dim RVal As Byte                           '[Stores status NetBIOS call]

    'STARTS ----------------------------------------------------
    RVal = NetBios(wNCB)                           '[Call Windows NET32 API]
    callNetBios = RVal
  End Function

  '-----------------------------------------------------------
  ' VERSION: 1.02
  ' DATE   : 4/11/2012
  '...........................................................
  ' DEFINITION/NOTES:
  '  NetBIOS call to add a NetBIOS name to the adapter table.
  '  Client is the name to add and LanaNum identifies the
  '  network adapter.
  '-----------------------------------------------------------
  Public Function NB_AddName(ByVal Client As String, _
                             ByVal LanaNum As Byte) As Byte

    Dim RVal As Byte                           '[Stores status NetBIOS call]
    Dim wNCB As New NCB                   '[NCB record used by NetBIOS call]

    'START -----------------------------------------------------
    Call InitNCB(wNCB)
    With wNCB
      .ncbCommand = NCBADDNAME                            '[Wait for finish]
      Call NB_PutString(Client, netbstrcs.netNameLen, .ncbName)
      .ncbLANAnum = LanaNum
    End With

    If slvStubIO Then
      If slvStubIOPrompt Then
        RVal = InputBox("Enter NB_AddName return", , netbErrors.nrcGOODRET)
      Else : RVal = netbErrors.nrcGOODRET
      End If
    Else : RVal = callNetBios(wNCB)                     '[Call Windows NET32 API]
    End If
    NB_AddName = RVal
  End Function

  '-----------------------------------------------------------
  ' VERSION: 1.01
  ' DATE   : 4/11/2012
  '...........................................................
  ' DEFINITION/NOTES:
  '  NetBIOS call to delete a NetBIOS name from the adapter
  '  table.  Hang up any active sessions before making this
  '  call.
  '  Client is the name to add and LanaNum identifies the
  '  network adapter.
  '-----------------------------------------------------------
  Public Function NB_DeleteName(ByVal Client As String, _
                                ByVal LanaNum As Byte) As Byte

    Dim RVal As Byte                           '[Stores status NetBIOS call]
    Dim wNCB As New NCB                   '[NCB record used by NetBIOS call]

    'START -----------------------------------------------------
    Call InitNCB(wNCB)
    With wNCB
      .ncbCommand = NCBDELNAME                            '[Wait for finish]
      Call NB_PutString(Client, netbstrcs.netNameLen, .ncbName)
      .ncbLANAnum = LanaNum
    End With

    If slvStubIO Then
      If slvStubIOPrompt Then
        RVal = InputBox("Enter NB_DeleteName return", , netbErrors.nrcGOODRET)
      Else : RVal = netbErrors.nrcGOODRET
      End If
    Else : RVal = callNetBios(wNCB)                     '[Call Windows NET32 API]
    End If
    NB_DeleteName = RVal
  End Function

  '-----------------------------------------------------------
  ' VERSION: 1.04
  ' DATE   : 6/25/2012
  '...........................................................
  ' DEFINITION/NOTES:
  '  NetBIOS call to get the status of an active session. Only
  '  excepts local names, not remote names. Use "*" for all
  '  local names.
  '
  '  Client is name of this PC (session) to check
  '  LanaNum is lana to use.
  '  SessStat is the status return.
  '-----------------------------------------------------------
  Public Function NB_SessionStat(ByVal Client As String, _
                                 ByVal LanaNum As Byte, _
                                 ByVal LSN As Byte, _
                                 ByRef SessStat As Byte, _
                                 ByRef OpenRecv As Byte, _
                                 ByRef OpenSend As Byte) As Byte

    Dim Lcnt As Byte                     '[Counter to check for desired LSN]
    Dim RVal As Byte                           '[Stores status NetBIOS call]
    Dim wNCB As New NCB                   '[NCB record used by NetBIOS call]
    Dim ptr As IntPtr                            '[temporary memory pointer]
    Dim SSDBuffer As New SessionHeader         '[Variable passed to NetBIOS]

    'START -----------------------------------------------------
    SessStat = 0
    With SSDBuffer
      ReDim .LocStatData(netbstrcs.netnumSess - 1)
      For Lcnt = 0 To netbstrcs.netnumSess - 1
        .LocStatData(Lcnt) = New SessionBuffer
        ReDim .LocStatData(Lcnt).RemoteName(netbstrcs.netNameLen - 1)
        ReDim .LocStatData(Lcnt).LocalName(netbstrcs.netNameLen - 1)
      Next
    End With
    ptr = Marshal.AllocHGlobal(Marshal.SizeOf(SSDBuffer))
    Marshal.StructureToPtr(SSDBuffer, ptr, False)

    Call InitNCB(wNCB)
    With wNCB
      .ncbCommand = NCBSSTAT                              '[Wait for finish]
      Call NB_PutString(Client, netbstrcs.netNameLen, .ncbName)
      .ncbLANAnum = LanaNum
      .ncbLength = CShort(Marshal.SizeOf(SSDBuffer))
      .ncbBuffer = ptr
    End With

    If slvStubIO Then
      SessStat = 3                                  '[Session okay & active]
      If slvStubIOPrompt Then
        RVal = InputBox("Enter NB_SessionStat return", _
                        , netbErrors.nrcGOODRET)
        SessStat = InputBox("Enter NB_SessionStat SessStat value", _
                            , SessStat)
      Else
        RVal = netbErrors.nrcGOODRET
      End If
    Else
      RVal = callNetBios(wNCB)                         '[Call Windows NET32 API]
      If RVal = netbErrors.nrcGOODRET Then
        SSDBuffer = CType(Marshal.PtrToStructure(ptr, GetType(SessionHeader)), SessionHeader)

        For Lcnt = 1 To SSDBuffer.NumSess
          If LSN = SSDBuffer.LocStatData(Lcnt - 1).LSN Then
            SessStat = SSDBuffer.LocStatData(Lcnt - 1).State
            OpenRecv = SSDBuffer.LocStatData(Lcnt - 1).ReceivesOutstanding
            OpenSend = SSDBuffer.LocStatData(Lcnt - 1).SendsOutstanding
          End If
        Next Lcnt
      End If
    End If
    Marshal.FreeHGlobal(ptr)
    NB_SessionStat = RVal
  End Function

  '-----------------------------------------------------------
  ' VERSION: 1.00
  ' DATE   : 6/20/2012
  '...........................................................
  ' DEFINITION/NOTES:
  '  NetBIOS call to get the status of an adapter. Only
  '  excepts local names, not remote names. Use "*" for all
  '  local names.
  '
  '  Client is name of this PC (session) to check
  '  LanaNum is lana to use.
  '  SessStat is the status return.
  '-----------------------------------------------------------
  Public Function NB_AdapterStat(ByVal Adapter As String, _
                                 ByVal LanaNum As Byte) As Byte

    Dim Lcnt As Byte                     '[Counter to check for desired LSN]
    Dim Rval As Byte                           '[Stores status NetBIOS call]
    Dim wNCB As New NCB                   '[NCB record used by NetBIOS call]
    Dim ptr As IntPtr                            '[temporary memory pointer]
    Dim AdapterBuffer As New Adapter_Status    '[Variable passed to NetBIOS]


    'START -----------------------------------------------------
    With AdapterBuffer
      ReDim .adapter_address(netbstrcs.netMAC - 1)
      ReDim .NameTable(netbstrcs.netnumNames - 1)
      For Lcnt = 0 To netbstrcs.netnumNames - 1
        .NameTable(Lcnt) = New Name_Buffer
        ReDim .NameTable(Lcnt).LocalName(netbstrcs.netNameLen - 1)
      Next
    End With
    ptr = Marshal.AllocHGlobal(Marshal.SizeOf(AdapterBuffer))
    Marshal.StructureToPtr(AdapterBuffer, ptr, False)

    Call InitNCB(wNCB)
    With wNCB
      .ncbCommand = NCBASTAT                              '[Wait for finish]
      Call NB_PutString(Adapter, netbstrcs.netNameLen, .ncbCallname)
      .ncbLANAnum = LanaNum
      .ncbLength = CShort(Marshal.SizeOf(AdapterBuffer))
      .ncbBuffer = ptr
    End With

    If slvStubIO Then
      If slvStubIOPrompt Then
        Rval = InputBox("Enter NB_AdapterStat return", _
                        , netbErrors.nrcGOODRET)
      Else
        Rval = netbErrors.nrcGOODRET
      End If
    Else
      Rval = callNetBios(wNCB)                         '[Call Windows NET32 API]
      If Rval = netbErrors.nrcGOODRET Then
        AdapterBuffer = CType(Marshal.PtrToStructure(ptr, GetType(Adapter_Status)), Adapter_Status)
      End If
    End If
    Marshal.FreeHGlobal(ptr)
    NB_AdapterStat = Rval
  End Function

  '-----------------------------------------------------------
  ' VERSION: 1.00
  ' DATE   : 6/21/2012
  '...........................................................
  ' DEFINITION/NOTES:
  '   Loops until session and/or adapters are ready.
  '
  '   Client is the name of the calling PC (this pc).
  '   Server is the name of PC being called (the slave).
  '   LanaNum identifies the network adapter.
  '   LSN is the session to check.
  '   AdapterOnly is true if only checking the adapter
  '
  '   NOTE: This code was written but never implemented. It
  '         was used to try and solve issue with Freescale
  '         Windows 2003 Server that appeared to have
  '         corrupted the network stack, where after initial
  '         session connection the 'A' from the controller
  '         was read in the NB_Receive call in this code, but
  '         NetBIOS API also returned error hex 40, which
  '         stands for 'Unusual Network Condition'.  This code
  '         never reported an error or that it I/F was busy,
  '         so it was not used.  However, if problem arises
  '         and it is used, it needs to be modified to only
  '         look for and perhaps wait for pending Recv or
  '         Sends - instead of waiting until none exist.
  '         Might be best to wait until other I/F has pending
  '         Send before issuing Recv - except I think this is
  '         supposed to be handled at API level (if not NICs).
  '-----------------------------------------------------------
  Public Function netLoopUntilReady(ByVal Client As String, _
                                    ByVal Slave As String, _
                                    ByVal LanaNum As Byte, _
                                    ByVal LSN As Byte, _
                                    ByVal AdapterOnly As Boolean) As Byte

    Dim Rval As Byte         '[Stores status NetBIOS call for local adapter]
    Dim Rval2 As Byte        '[Stores status NetBIOS call for slave adapter]
    Dim Rval3 As Byte              '[Stores status NetBIOS call for session]
    Dim Wcnt As Long                  '[Number of loops to wait for counter]
    Dim SessStat As Byte   '[Status from session - 3 is Session established]
    Dim OpenRecv As Byte                       '[Number of pending receives]
    Dim OpenSend As Byte                          '[Number of pending sends]
    Dim ExitLoop As Boolean

    'STARTS ----------------------------------------------------
    If slvStubIO Then
      netLoopUntilReady = netbErrors.nrcGOODRET
    Else
      Wcnt = 0
      Rval = netbErrors.nrcGOODRET
      Rval2 = netbErrors.nrcGOODRET
      Rval3 = netbErrors.nrcGOODRET
      ExitLoop = False
      Do
        DoEvents()
        Rval = NB_AdapterStat(Client, LanaNum)
        Rval2 = NB_AdapterStat(Slave, LanaNum)

        '[Allow to exit of okay or error not one being looped on]
        ExitLoop = (Rval = netbErrors.nrcGOODRET) Or _
                   ((Rval <> netbErrors.nrcSYSTEM) And (Rval <> netbErrors.nrcIFBUSY) And _
                    (Rval <> netbErrors.nrcTOOMANY))
        If (Rval = netbErrors.nrcGOODRET) Then
          ExitLoop = (Rval2 = netbErrors.nrcGOODRET) Or _
                     ((Rval2 <> netbErrors.nrcSYSTEM) And (Rval2 <> netbErrors.nrcIFBUSY) And _
                      (Rval2 <> netbErrors.nrcTOOMANY))
        End If

        If (AdapterOnly = False) And (Rval = netbErrors.nrcGOODRET) And (Rval2 = netbErrors.nrcGOODRET) Then
          Rval3 = NB_SessionStat(Client, LanaNum, LSN, SessStat, OpenRecv, OpenSend)
          If (Rval3 = netbErrors.nrcGOODRET) Then
            If (OpenRecv > 0) Or (OpenSend > 0) Or (SessStat = 0) Or (SessStat = 1) Or (SessStat = 2) Then
              '[Wait until pending sends/receives done, or session established]
              Call MsgBox("TPJ OpenR=" + CStr(OpenRecv) + " OpenS=" + CStr(OpenSend) + " SessS=" + CStr(SessStat))
              ExitLoop = False
            Else
              ExitLoop = True
            End If
          ElseIf (Rval3 = netbErrors.nrcIFBUSY) Or (Rval3 = netbErrors.nrcSYSTEM) Or _
                 (Rval3 = netbErrors.nrcTOOMANY) Then
            '[Wait for this error state to clear]
            ExitLoop = False
            Call MsgBox("TPJ In session handling error state Rval3=" + CStr(Rval3))
          Else
            '[Error state beyond waiting for correction]
            ExitLoop = True
          End If
        End If
        Wcnt = Wcnt + 1
        If (Rval <> 0) Or (Rval2 <> 0) Then Call MsgBox("TPJ inLoop Rval=" + CStr(Rval) + " Rval2=" + CStr(Rval2))
      Loop Until (ExitLoop = True) Or (Wcnt > 6)

      If (Wcnt > 6) Then
        Call MsgBox("tpj Wcnt=" + CStr(Wcnt))
      End If

      If (Rval = netbErrors.nrcGOODRET) Then Rval = Rval2
      If (AdapterOnly = False) And (Rval = netbErrors.nrcGOODRET) Then Rval = Rval3
    End If
    If Rval <> 0 Then Call MsgBox("TPJ Loop Rval=" + CStr(Rval))
    netLoopUntilReady = Rval
  End Function

  '-----------------------------------------------------------
  ' VERSION: 1.02
  ' DATE   : 4/11/2012
  '...........................................................
  ' DEFINITION/NOTES:
  '  NetBIOS call to call another PC for a session connection.
  '
  '  wNCB is the network control block to use.
  '  Client is the name of the calling PC (this pc).
  '  Server is the name of PC being called (the slave).
  '  LanaNum identifies the network adapter.
  '  If a connection is made, Lsn holds the session number.
  '
  '  This command also sets the timeouts for all send/receive
  '  commands that use this LSN.
  '-----------------------------------------------------------
  Public Function NB_Call(ByRef wNCB As NCB, _
                          ByVal Client As String, _
                          ByVal Server As String, _
                          ByVal LanaNum As Byte) As Byte

    Dim RVal As Byte                           '[Stores status NetBIOS call]

    'STARTS ----------------------------------------------------
    Call InitNCB(wNCB)
    With wNCB
      .ncbCommand = NCBCALL
      Call NB_PutString(Client, netbstrcs.netNameLen, .ncbName)
      Call NB_PutString(Server, netbstrcs.netNameLen, .ncbCallname)
      .ncbRTO = ncbRcvTimeOut
      .ncbSTO = ncbSndTimeOut
      .ncbLANAnum = LanaNum
    End With
    If slvStubIO Then
      wNCB.ncbCmdCplt = netbErrors.nrcGOODRET
      wNCB.ncbLSN = 1
      If slvStubIOPrompt Then
        RVal = InputBox("Enter NB_Call return", , netbErrors.nrcGOODRET)
        wNCB.ncbCmdCplt = RVal
        wNCB.ncbLSN = InputBox("Enter NB_Call LSN value", , 1)
      Else : RVal = netbErrors.nrcGOODRET
      End If
    Else : RVal = callNetBios(wNCB)                     '[Call Windows NET32 API]
    End If
    NB_Call = RVal
  End Function

  '-----------------------------------------------------------
  ' VERSION: 1.02
  ' DATE   : 4/11/2012
  '...........................................................
  ' DEFINITION/NOTES:
  '  Resets the adapter/protocol based upon the LanaNum passed
  '  in.  LanaNum identifies the network adapter.
  '
  '-----------------------------------------------------------
  Public Function NB_Reset(ByVal LanaNum As Byte) As Byte

    Dim RVal As Byte                           '[Stores status NetBIOS call]
    Dim wNCB As New NCB                       '[NCB record used by NetBIOS call]

    'STARTS ----------------------------------------------------
    Call InitNCB(wNCB)

    With wNCB
      .ncbCommand = NCBRESET
      .ncbLSN = 0
      .ncbLANAnum = LanaNum
      .ncbCallname(0) = 254                  '[Set maximum NetBIOS sessions]
      .ncbCallname(2) = 254               '[Set maximum NetBIOS table names]
      .ncbCallname(3) = 0                       '[Use any name for commands]
    End With

    If slvStubIO Then
      If slvStubIOPrompt Then
        RVal = InputBox("Enter NB_Reset return", , netbErrors.nrcGOODRET)
      Else : RVal = netbErrors.nrcGOODRET
      End If
    Else : RVal = callNetBios(wNCB)                     '[Call Windows NET32 API]
    End If
    NB_Reset = RVal
  End Function


  '-----------------------------------------------------------
  ' VERSION: 1.02
  ' DATE   : 4/12/2012
  '...........................................................
  ' DEFINITION/NOTES:
  '  Generates a list of the adapter/protocol numbers (lanas).
  '  This list is stored in public and should only have to
  '  be issued once when starting program.  However, with
  '  Windows plug-n-play it is possible that the network
  '  configuration will change without a reboot.
  '
  '  Used in conjunction with NB_Listen or NB_Call to make a
  '  slave PC connection.
  '-----------------------------------------------------------
  Public Function NB_EnumLanas(ByRef LANAS As LANA_ENUM) As Byte

    Dim RVal As Byte                           '[Stores status NetBIOS call]
    Dim wNCB As New NCB                   '[NCB record used by NetBIOS call]
    Dim ptr As IntPtr                            '[temporary memory pointer]

    'STARTS ----------------------------------------------------
    Call InitNCB(wNCB)
    Call InitLANA_ENUM(LANAS)
    ptr = Marshal.AllocHGlobal(Marshal.SizeOf(LANAS))
    Marshal.StructureToPtr(LANAS, ptr, True)

    With wNCB
      .ncbCommand = NCBENUM
      .ncbLength = CShort(Marshal.SizeOf(LANAS))
      .ncbBuffer = ptr                           '[Set global far ptr to Lanas]
    End With

    If slvStubIO Then
      If slvStubIOPrompt Then
        RVal = InputBox("Enter NB_EnumLanas return", , netbErrors.nrcGOODRET)
      Else : RVal = netbErrors.nrcGOODRET
      End If
      LANAS.Length = 1                   '[Setup a lana for "network" control]
      LANAS.LANA(0) = 1
    Else
      RVal = callNetBios(wNCB)                           '[Call Windows NET32 API]
      LANAS = CType(Marshal.PtrToStructure(ptr, GetType(LANA_ENUM)), LANA_ENUM)
    End If
    Marshal.FreeHGlobal(ptr)
    wNCB = Nothing
    NB_EnumLanas = RVal
  End Function

  '-----------------------------------------------------------
  ' VERSION: 1.02
  ' DATE   : 4/11/2012
  '...........................................................
  ' DEFINITION/NOTES:
  '  Listens on a given LanaNum for a connection.
  '
  '  wNCB identifies the NCB to use for the command.
  '  LanaNum identifies the network adapter/protocol.
  '  Client identifies the name of the PC calling (slave).
  '  Server identifies the name of the PC listening (this PC).
  '  Wait indicates whether or not to wait for NetBIOS call
  '  to finish.
  '
  '  Expects the calling routine to obtain the LSN and
  '  evaluate the wNCB contents for success.
  '  This command also sets the timeouts for all send/receive
  '  commands that use this LSN.
  '-----------------------------------------------------------
  Public Function NB_Listen(ByRef wNCB As NCB, _
                            ByVal LanaNum As Byte, _
                            ByVal Server As String, _
                            ByVal Client As String, _
                            ByVal Wait As Boolean) As Byte

    Dim RVal As Byte                           '[Stores status NetBIOS call]

    'STARTS ----------------------------------------------------
    Call InitNCB(wNCB)

    With wNCB
      If Wait Then
        .ncbCommand = NCBLISTEN
      Else : .ncbCommand = NCBLISTEN + NCBNOWAIT
      End If
      .ncbLANAnum = LanaNum
      Call NB_PutString(Server, netbstrcs.netNameLen, .ncbName)
      Call NB_PutString(Client, netbstrcs.netNameLen, .ncbCallname)
      .ncbRTO = ncbRcvTimeOut
      .ncbSTO = ncbSndTimeOut
    End With

    If slvStubIO Then
      If slvStubIOPrompt Then
        RVal = InputBox("Enter NB_Listen return", , netbErrors.nrcGOODRET)
      Else : RVal = netbErrors.nrcGOODRET
      End If
    Else : RVal = callNetBios(wNCB)                     '[Call Windows NET32 API]
    End If
    NB_Listen = RVal
  End Function

  '-----------------------------------------------------------
  ' VERSION: 1.02
  ' DATE   : 4/18/2012
  '...........................................................
  ' DEFINITION/NOTES:
  '  Sends a buffer of data based upon the LSN and LanaNum
  '  passed in. Unlike a receive command, a failed send
  '  command cause the session to be dropped, thus it has a
  '  longer time-out and no loop support.
  '
  '  wNCB identifies the NCB to use for the command.
  '  LanaNum identifies the network adapter/protocol.
  '  LSN identifies the session to use.
  '  BufferSize contains the number of bytes to send.
  '  Buffer contains the data to be sent.
  '
  '  Because VB variable pointer limitations, this routine
  '  must wait for the send to occur.  See the notes at the
  '  top of this file for details.
  '-----------------------------------------------------------
  Public Function NB_Send(ByVal LanaNum As Byte, _
                          ByVal LSN As Byte, _
                          ByRef BufferSize As Int16, _
                          ByVal Buffer As String) As Byte

    Dim RVal As Byte                           '[Stores status NetBIOS call]
    Dim wNCB As New NCB                   '[NCB record used by NetBIOS call]
    Dim ptr As IntPtr                            '[temporary memory pointer]
    Dim wBuffer As New DataBuffer                    '[Structure for buffer]

    'STARTS ----------------------------------------------------
    Call InitNCB(wNCB)
    ReDim wBuffer.ncbBufStat(netbstrcs.netbuffer - 1)
    Call NB_PutString(Buffer, BufferSize, wBuffer.ncbBufStat)
    ptr = Marshal.AllocHGlobal(Marshal.SizeOf(wBuffer))
    Marshal.StructureToPtr(wBuffer, ptr, False)

    With wNCB
      .ncbCommand = NCBSEND                 '[Always wait with this command]
      .ncbLANAnum = LanaNum
      .ncbLSN = LSN
      .ncbBuffer = ptr
      .ncbLength = BufferSize           '[Length to send, not entire buffer]
    End With

    If slvStubIO Then
      If slvStubIOPrompt Then
        RVal = InputBox("Enter NB_Send return", , netbErrors.nrcGOODRET)
      Else : RVal = netbErrors.nrcGOODRET
      End If
      NB_Send = RVal
    Else
      RVal = callNetBios(wNCB)
      BufferSize = wNCB.ncbLength             '[Return number of bytes sent]
      NB_Send = wNCB.ncbCmdCplt                 '[Return final command code]
    End If
    Marshal.FreeHGlobal(ptr)
  End Function

  '-----------------------------------------------------------
  ' VERSION: 1.02
  ' DATE   : 4/11/2012
  '...........................................................
  ' DEFINITION/NOTES:
  '  Receives a buffer of data based upon the LSN and LanaNum
  '  passed in.
  '
  '  LanaNum identifies the network adapter/protocol.
  '  LSN identifies the session to use.
  '  BufferSize contains max. number of bytes to be received.
  '  Buffer is String where the received data is to be placed.
  '
  '  Because VB variable pointer limitations, this routine
  '  must wait for the receive to occur.  
  '-----------------------------------------------------------
  Public Function NB_Receive(ByVal LanaNum As Byte, _
                             ByVal LSN As Byte, _
                             ByRef BufferSize As Int16, _
                             ByRef Buffer As String) As Byte

    Dim RVal As Byte                           '[Stores status NetBIOS call]
    Dim wNCB As New NCB                   '[NCB record used by NetBIOS call]
    Dim ptr As IntPtr                            '[temporary memory pointer]
    Dim wBuffer As New DataBuffer                    '[Structure for buffer]

    'STARTS ----------------------------------------------------
    ReDim wBuffer.ncbBufStat(netbstrcs.netbuffer - 1)
    ptr = Marshal.AllocHGlobal(Marshal.SizeOf(wBuffer))
    Marshal.StructureToPtr(wBuffer, ptr, False)
    Call InitNCB(wNCB)
    With wNCB
      .ncbCommand = NCBRECV                  '[Always wait for this command]
      .ncbLANAnum = LanaNum
      .ncbLSN = LSN
      .ncbBuffer = ptr
      .ncbLength = BufferSize
    End With

    If slvStubIO Then
      Buffer = StrDup(BufferSize, "A")        '[Always A for Ack stub calls]
      If slvStubIOPrompt Then
        RVal = InputBox("Enter NB_Receive return", , netbErrors.nrcGOODRET)
        Buffer = InputBox("Enter NB_Receive Buffer value", , Buffer)
      Else : RVal = netbErrors.nrcGOODRET
      End If
      BufferSize = Len(Buffer)
      NB_Receive = RVal                    '[Return final status of command]
    Else
      Buffer = ""
      BufferSize = 0
      RVal = callNetBios(wNCB)
      If (RVal = netbErrors.nrcGOODRET) Or _
         (RVal = netbErrors.nrcINCOMP) Then
        BufferSize = wNCB.ncbLength
        wBuffer = CType(Marshal.PtrToStructure(ptr, GetType(DataBuffer)), DataBuffer)
        Call NB_GetString(wBuffer.ncbBufStat, BufferSize, Buffer)
      End If
      NB_Receive = wNCB.ncbCmdCplt         '[Return final status of command]
    End If
    Marshal.FreeHGlobal(ptr)
  End Function

  '-----------------------------------------------------------
  ' VERSION: 1.02
  ' DATE   : 4/11/2012
  '...........................................................
  ' DEFINITION/NOTES:
  '  Cancels any outstanding NetBIOS command.  Check the
  '  NetBIOS documentation for commands that can be canceled.
  '
  '  cNCB is the NCB of the command to be canceled.
  '  LanaNum identifies the adapter/protocol to use.
  '
  '  WARNING: Cancelling a Send command causes the session
  '           to be dropped.
  '-----------------------------------------------------------
  Public Function NB_Cancel(ByRef cNCB As NCB, _
                            ByVal LanaNum As Byte) As Byte

    Dim RVal As Byte                           '[Stores status NetBIOS call]
    Dim wNCB As New NCB                   '[NCB record used by NetBIOS call]
    Dim ptr As IntPtr                            '[temporary memory pointer]

    'STARTS ----------------------------------------------------
    ptr = Marshal.AllocHGlobal(Marshal.SizeOf(cNCB))
    Marshal.StructureToPtr(cNCB, ptr, False)
    Call InitNCB(wNCB)
    With wNCB
      .ncbCommand = NCBCANCEL
      .ncbLANAnum = LanaNum
      .ncbBuffer = ptr                                   '[Set ptr to cNCB]
    End With

    If slvStubIO Then
      If slvStubIOPrompt Then
        RVal = InputBox("Enter NB_Cancel return", , netbErrors.nrcGOODRET)
      Else : RVal = netbErrors.nrcGOODRET
      End If
    Else : RVal = callNetBios(wNCB)                     '[Call Windows NET32 API]
    End If
    NB_Cancel = RVal
    Marshal.FreeHGlobal(ptr)
  End Function

  '-----------------------------------------------------------
  ' VERSION: 1.02
  ' DATE   : 4/11/2012
  '...........................................................
  ' DEFINITION/NOTES:
  '  Hangs up an existing session.
  '
  '  LSN Identifies the session to close.
  '  LanaNum identifies the adapter/protocol to use.
  '
  '-----------------------------------------------------------
  Public Function NB_HangUp(ByRef LSN As Byte, _
                            ByVal LanaNum As Byte) As Byte

    Dim RVal As Byte                           '[Stores status NetBIOS call]
    Dim wNCB As New NCB                   '[NCB record used by NetBIOS call]

    'STARTS ----------------------------------------------------
    Call InitNCB(wNCB)
    With wNCB
      .ncbCommand = NCBHANGUP
      .ncbLANAnum = LanaNum
      .ncbLSN = LSN
    End With

    If slvStubIO Then
      If slvStubIOPrompt Then
        RVal = InputBox("Enter NB_HangUp return", , netbErrors.nrcGOODRET)
      Else : RVal = netbErrors.nrcGOODRET
      End If
    Else : RVal = callNetBios(wNCB)                     '[Call Windows NET32 API]
    End If
    LSN = 0
    Call Netio.Fire_onCheckConnect()
    NB_HangUp = RVal
  End Function
End Module

 Leave a Reply

(required)

(required)

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>