NetBIOS
C# Signature:
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct _NCB
{
public Commands ncb_command; /* command code */
public byte ncb_retcode; /* return code */
public byte ncb_lsn; /* local session number */
public byte ncb_num; /* number of our network name */
//[MarshalAs(UnmanagedType.ByValArray, SizeConst = NCBNAMSZ)]
//[MarshalAs(UnmanagedType.LPStr)]
//[MarshalAs(UnmanagedType.LPArray)]
public IntPtr ncb_buffer; /* address of message buffer */
public ushort ncb_length; /* size of message buffer */
[MarshalAs(UnmanagedType.ByValArray, SizeConst = NativeMethods.NCBNAMSZ)]
public byte[] ncb_callname; /* blank-padded name of remote */
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = NativeMethods.NCBNAMSZ)]
public byte[] ncb_name; /* our blank-padded netname */
public byte ncb_rto; /* rcv timeout/retry count */
public byte ncb_sto; /* send timeout/sys timeout */
public IntPtr postroutine;//void (CALLBACK *ncb_post)( struct _NCB * ); /* POST routine address */
public byte ncb_lana_num; /* lana (adapter) number */
public byte ncb_cmd_cplt; /* 0xff => commmand pending */
[MarshalAs(UnmanagedType.LPArray, SizeConst=10)]
public byte[/*10*/] ncb_reserve; /* reserved, used by BIOS */
public IntPtr ncb_event; /* HANDLE to Win32 event which */
/* will be set to the signalled */
/* state when an ASYNCH command */
/* completes */
}
[DllImport("netapi32.dll", SetLastError=true)]
static extern byte Netbios(ref _NCB controlBlock);
VB Signature:
Private Declare Function Netbios Lib "netapi32.dll" ( _
ByRef pncb As NCB _
) As Byte
User-Defined Types:
Private Const NCBNAMSZ As Integer = 16
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi)> _
Private Structure NCB
Dim ncb_command As Byte
Dim ncb_retcode As Byte
Dim ncb_lsn As Byte
Dim ncb_num As Byte
Dim ncb_buffer As IntPtr
Dim ncb_length As Short
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=NCBNAMSZ)> Dim ncb_callname As String
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=NCBNAMSZ)> Dim ncb_name As String
Dim ncb_rto As Byte
Dim ncb_sto As Byte
Dim ncb_post As IntPtr
Dim ncb_lana_num As Byte
Dim ncb_cmd_cplt As Byte
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=10)> Dim ncb_reserve() As Byte
Dim ncb_event As IntPtr
End Structure
VB.Net Sample Code:
Private Const NCBNAMSZ As Integer = 16
Private Const MAX_LANA As Integer = 254
Private Const NCBRESET As Integer = &H32
Private Const NCBASTAT As Integer = &H33
Private Const NCBENUM As Integer = &H37
<StructLayout(LayoutKind.Sequential)> _
Private Structure ASTAT
Dim adapt As ADAPTER_STATUS
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=30)> Dim NameBuff() As NAME_BUFFER
End Structure
' Get the MAC Address of a remote PC
Function GetMACAddress(ByVal RemoteIP As String) As String
Dim sb As New StringBuilder
Dim myNcb As New NCB
Dim myAdapt As New ADAPTER_STATUS
Dim myASTAT As New ASTAT
Dim myLana As New LANA_ENUM
Dim ptr As IntPtr
Dim i As Integer
Dim bRet, FirstLANA As Byte
' First, we'll need to discover which LANA number is being used.
' So, we create a LANA_ENUM buffer (with a bit of pointer magic)
ptr = Marshal.AllocHGlobal(Marshal.SizeOf(myLana))
Marshal.StructureToPtr(myLana, ptr, False)
' load the NCB
myNcb.ncb_command = NCBENUM
myNcb.ncb_length = CShort(Marshal.SizeOf(myLana))
myNcb.ncb_buffer = ptr
' execute the NetBIOS command
bRet = Netbios(myNcb)
If bRet <> 0 Then
Marshal.FreeHGlobal(ptr)
Throw New ApplicationException("Can't get the list of LANAs, error code=" & bRet)
Return Nothing
End If
' cast it back with pointer magic
myLana = CType(Marshal.PtrToStructure(ptr, GetType(LANA_ENUM)), LANA_ENUM)
FirstLANA = myLana.lana(0)
' Next we do a "reset" on the NetBIOS interface
myNcb.ncb_command = NCBRESET
myNcb.ncb_lana_num = FirstLANA
' execute the NetBIOS command
bRet = Netbios(myNcb)
If bRet <> 0 Then
Marshal.FreeHGlobal(ptr)
Throw New ApplicationException("Can't Reset the NetBIOS interface, error code=" & bRet)
Return Nothing
End If
' Create an Adapater Status packet (with more pointer magic)
Marshal.FreeHGlobal(ptr)
myASTAT.adapt = myAdapt
ptr = Marshal.AllocHGlobal(Marshal.SizeOf(myASTAT))
Marshal.StructureToPtr(myASTAT, ptr, False)
' Now we load up our adapter request
myNcb.ncb_command = NCBASTAT
myNcb.ncb_lana_num = FirstLANA
myNcb.ncb_callname = RemoteIP.PadRight(NCBNAMSZ, " "c)
myNcb.ncb_buffer = ptr
myNcb.ncb_length = CShort(Marshal.SizeOf(myASTAT))
' execute the NetBIOS command
bRet = Netbios(myNcb)
If bRet <> 0 Then
Marshal.FreeHGlobal(ptr)
Throw New ApplicationException("Can't get the Adapter Status, error code=" & bRet)
Return Nothing
End If
' cast it back with pointer magic
myASTAT = CType(Marshal.PtrToStructure(ptr, GetType(ASTAT)), ASTAT)
' make a string version of the MAC address
For i = 0 To 5
sb.AppendFormat("{0:X2}:", myASTAT.adapt.adapter_address(i))
Next
Marshal.FreeHGlobal(ptr)
Return sb.ToString.TrimEnd(":"c)
End Function
Alternative Managed API:
'-----------------------------------------------------------
' 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
<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
Última actualización