A NetBIOS provider must closely couple its connection-oriented services with its connectionless services. However, through TPI, a STREAMS stack must declare itself as either a connection-oriented (T_COTS) or a connectionless (T_CLTS) provider. Therefore a STREAMS NetBIOS provider has to be implemented via two drivers: a T_COTS driver and a T_CTLS driver. For example, NetBIOS over TCP/IP is provided by the following STREAMS drivers:
\Device\Streams\nbt
\Device\Streams\nbdg
Example: DriverEntry Routine for nbt.sys
#include <ntddk.h> #include <tdi.h> #include <stream.h> #include <xti.h> ********************** extern struct streamtab nbtinfo, nbdginfo; static struct nbaddr BroadcastName = { NBBROADCAST | NBGROUPNM, "*" }; static STREAMS_TDI_ADDRESS_INFO AddressInfo = { sizeof(BroadcastName), // Broadcast address length TDI_ADDRESS_TYPE_NETBIOS, // TDI address type TRUE, // Directed message goes farther // than broadcast or multicast &BroadcastName // Broadcast address }; STREAMS_TDI_INFO NbtTdiInfo = { T_COTS_ORD, // SERV_type &nbdginfo, // Partner streamtab T_CLTS, // Partner SERV_type 0, // Option length NULL, // Option pointer TRUE, // Reuseaddr set by default 1, // One address info structure &AddressInfo // AddressInfo }; STREAMS_TDI_INFO NbdgTdiInfo = { T_CLTS, // SERV_type &nbtinfo, // Partner streamtab T_COTS_ORD, // Partner SERV_type 0, // Option length NULL, // Option pointer TRUE, // Reuseaddr set by default 1, // One address info structure &AddressInfo // AddressInfo }; NTSTATUS DriverEntry( IN PDRIVER_OBJECT driver, PUNICODE_STRING description ) { NTSTATUS status; status = ExtractRegistry(); if (status != STATUS_SUCCESS) { return(status); } if (nbtinit()) { return(STATUS_NO_MEMORY); } status = StrmRegisterDriver(driver, &nbtinfo, NULL, &NbtTdiInfo); if (status != STATUS_SUCCESS) { return(status); } status = StrmRegisterDriver(driver, &nbdginfo, NULL, &NbdgTdiInfo); if (status != STATUS_SUCCESS) { return(status); } return(status); }